Addressing comments for PR 2176.
BLD-529.
This commit is contained in:
@@ -83,7 +83,7 @@ class StubYouTubeHandler(StubHttpRequestHandler):
|
||||
'duration': 60,
|
||||
})
|
||||
})
|
||||
response = callback + '({})'.format(json.dumps(data))
|
||||
response = "{cb}({data})".format(cb=callback, data=json.dumps(data))
|
||||
|
||||
self.send_response(200, content=response, headers={'Content-type': 'text/html'})
|
||||
self.log_message("Youtube: sent response {}".format(message))
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
# Stub Youtube API
|
||||
window.YT =
|
||||
Player: ->
|
||||
getDuration: ->
|
||||
60
|
||||
PlayerState:
|
||||
UNSTARTED: -1
|
||||
ENDED: 0
|
||||
PLAYING: 1
|
||||
PAUSED: 2
|
||||
BUFFERING: 3
|
||||
CUED: 5
|
||||
ready: (f) -> f()
|
||||
|
||||
window.STATUS = window.YT.PlayerState
|
||||
|
||||
oldAjaxWithPrefix = window.jQuery.ajaxWithPrefix
|
||||
|
||||
window.onTouchBasedDevice = ->
|
||||
navigator.userAgent.match /iPhone|iPod|iPad/i
|
||||
|
||||
jasmine.stubbedCaption =
|
||||
end: [3120, 6270, 8490, 21620, 24920, 25750, 27900, 34380, 35550, 40250]
|
||||
start: [1180, 3120, 6270, 14910, 21620, 24920, 25750, 27900, 34380, 35550]
|
||||
text: [
|
||||
"MICHAEL CIMA: So let's do the first one here.",
|
||||
"Vacancies, where do they come from?",
|
||||
"Well, imagine a perfect crystal.",
|
||||
"Now we know at any temperature other than absolute zero there's enough",
|
||||
"energy going around that some atoms will have more energy",
|
||||
"than others, right?",
|
||||
"There's a distribution.",
|
||||
"If I plot energy here and number, these atoms in the crystal will have a",
|
||||
"distribution of energy.",
|
||||
"And some will have quite a bit of energy, just for a moment."
|
||||
]
|
||||
|
||||
# For our purposes, we need to make sure that the function $.ajaxWithPrefix
|
||||
# does not fail when during tests a captions file is requested.
|
||||
# It is originally defined in
|
||||
#
|
||||
# common/static/coffee/src/ajax_prefix.js
|
||||
#
|
||||
# We will replace it with a function that does:
|
||||
#
|
||||
# 1.) Return a hard coded captions object if the file name contains 'Z5KLxerq05Y'.
|
||||
# 2.) Behaves the same a as the origianl in all other cases.
|
||||
|
||||
window.jQuery.ajaxWithPrefix = (url, settings) ->
|
||||
if not settings
|
||||
settings = url
|
||||
url = settings.url
|
||||
success = settings.success
|
||||
data = settings.data
|
||||
|
||||
if url.match(/Z5KLxerq05Y/g) isnt null or url.match(/7tqY6eQzVhE/g) isnt null or url.match(/cogebirgzzM/g) isnt null
|
||||
if window.jQuery.isFunction(success) is true
|
||||
success jasmine.stubbedCaption
|
||||
else if window.jQuery.isFunction(data) is true
|
||||
data jasmine.stubbedCaption
|
||||
else
|
||||
oldAjaxWithPrefix.apply @, arguments
|
||||
|
||||
# Time waitsFor() should wait for before failing a test.
|
||||
window.WAIT_TIMEOUT = 5000
|
||||
|
||||
jasmine.getFixtures().fixturesPath += 'fixtures'
|
||||
|
||||
jasmine.stubbedMetadata =
|
||||
'7tqY6eQzVhE':
|
||||
id: '7tqY6eQzVhE'
|
||||
duration: 300
|
||||
'cogebirgzzM':
|
||||
id: 'cogebirgzzM'
|
||||
duration: 200
|
||||
bogus:
|
||||
duration: 100
|
||||
|
||||
jasmine.fireEvent = (el, eventName) ->
|
||||
if document.createEvent
|
||||
event = document.createEvent "HTMLEvents"
|
||||
event.initEvent eventName, true, true
|
||||
else
|
||||
event = document.createEventObject()
|
||||
event.eventType = eventName
|
||||
event.eventName = eventName
|
||||
if document.createEvent
|
||||
el.dispatchEvent(event)
|
||||
else
|
||||
el.fireEvent("on" + event.eventType, event)
|
||||
|
||||
jasmine.stubbedHtml5Speeds = ['0.75', '1.0', '1.25', '1.50']
|
||||
|
||||
jasmine.stubRequests = ->
|
||||
spyOn($, 'ajax').andCallFake (settings) ->
|
||||
if match = settings.url.match /youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/
|
||||
status = match[1].split('_')
|
||||
if status and status[0] is 'status'
|
||||
{
|
||||
always: (callback) ->
|
||||
callback.call(window, {}, status[1])
|
||||
error: (callback) ->
|
||||
callback.call(window, {}, status[1])
|
||||
done: (callback) ->
|
||||
callback.call(window, {}, status[1])
|
||||
}
|
||||
else if settings.success
|
||||
# match[1] - it's video ID
|
||||
settings.success data: jasmine.stubbedMetadata[match[1]]
|
||||
else {
|
||||
always: (callback) ->
|
||||
callback.call(window, {}, 'success')
|
||||
done: (callback) ->
|
||||
callback.call(window, {}, 'success')
|
||||
}
|
||||
else if match = settings.url.match /static(\/.*)?\/subs\/(.+)\.srt\.sjson/
|
||||
settings.success jasmine.stubbedCaption
|
||||
else if settings.url.match /.+\/problem_get$/
|
||||
settings.success html: readFixtures('problem_content.html')
|
||||
else if settings.url == '/calculate' ||
|
||||
settings.url.match(/.+\/goto_position$/) ||
|
||||
settings.url.match(/event$/) ||
|
||||
settings.url.match(/.+\/problem_(check|reset|show|save)$/)
|
||||
# do nothing
|
||||
else
|
||||
throw "External request attempted for #{settings.url}, which is not defined."
|
||||
|
||||
jasmine.stubYoutubePlayer = ->
|
||||
YT.Player = ->
|
||||
obj = jasmine.createSpyObj 'YT.Player', ['cueVideoById', 'getVideoEmbedCode',
|
||||
'getCurrentTime', 'getPlayerState', 'getVolume', 'setVolume', 'loadVideoById',
|
||||
'playVideo', 'pauseVideo', 'seekTo', 'getDuration', 'getAvailablePlaybackRates', 'setPlaybackRate']
|
||||
obj['getDuration'] = jasmine.createSpy('getDuration').andReturn 60
|
||||
obj['getAvailablePlaybackRates'] = jasmine.createSpy('getAvailablePlaybackRates').andReturn [0.75, 1.0, 1.25, 1.5]
|
||||
obj
|
||||
|
||||
jasmine.stubVideoPlayer = (context, enableParts, html5=false) ->
|
||||
suite = context.suite
|
||||
currentPartName = suite.description while suite = suite.parentSuite
|
||||
if html5 == false
|
||||
loadFixtures 'video.html'
|
||||
else
|
||||
loadFixtures 'video_html5.html'
|
||||
jasmine.stubRequests()
|
||||
YT.Player = undefined
|
||||
window.OldVideoPlayer = undefined
|
||||
jasmine.stubYoutubePlayer()
|
||||
return new Video '#example', '.75:7tqY6eQzVhE,1.0:cogebirgzzM'
|
||||
|
||||
# Add custom matchers
|
||||
beforeEach ->
|
||||
@addMatchers
|
||||
toHaveAttrs: (attrs) ->
|
||||
element = @.actual
|
||||
result = true
|
||||
if $.isEmptyObject attrs
|
||||
return false
|
||||
$.each attrs, (name, value) ->
|
||||
result = result && element.attr(name) == value
|
||||
return result
|
||||
|
||||
toBeInRange: (min, max) ->
|
||||
return min <= @.actual && @.actual <= max
|
||||
|
||||
toBeInArray: (array) ->
|
||||
return $.inArray(@.actual, array) > -1
|
||||
|
||||
@addMatchers imagediff.jasmine
|
||||
|
||||
# Stub jQuery.cookie
|
||||
$.cookie = jasmine.createSpy('jQuery.cookie').andReturn '1.0'
|
||||
|
||||
# Stub jQuery.qtip
|
||||
$.fn.qtip = jasmine.createSpy 'jQuery.qtip'
|
||||
|
||||
# Stub jQuery.scrollTo
|
||||
$.fn.scrollTo = jasmine.createSpy 'jQuery.scrollTo'
|
||||
290
common/lib/xmodule/xmodule/js/spec/helper.js
Normal file
290
common/lib/xmodule/xmodule/js/spec/helper.js
Normal file
@@ -0,0 +1,290 @@
|
||||
(function ($, undefined) {
|
||||
var oldAjaxWithPrefix = $.ajaxWithPrefix;
|
||||
|
||||
// Stub YouTube API.
|
||||
window.YT = {
|
||||
Player: function () {
|
||||
var Player = jasmine.createSpyObj(
|
||||
'YT.Player',
|
||||
[
|
||||
'cueVideoById', 'getVideoEmbedCode', 'getCurrentTime',
|
||||
'getPlayerState', 'getVolume', 'setVolume',
|
||||
'loadVideoById', 'getAvailablePlaybackRates', 'playVideo',
|
||||
'pauseVideo', 'seekTo', 'getDuration', 'setPlaybackRate',
|
||||
'getPlaybackQuality'
|
||||
]
|
||||
);
|
||||
|
||||
Player.getDuration.andReturn(60);
|
||||
Player.getAvailablePlaybackRates.andReturn(['0.50', '1.0', '1.50', '2.0']);
|
||||
|
||||
return Player;
|
||||
},
|
||||
|
||||
PlayerState: {
|
||||
UNSTARTED: -1,
|
||||
ENDED: 0,
|
||||
PLAYING: 1,
|
||||
PAUSED: 2,
|
||||
BUFFERING: 3,
|
||||
CUED: 5
|
||||
},
|
||||
ready: function (f) {
|
||||
return f();
|
||||
}
|
||||
};
|
||||
|
||||
window.STATUS = window.YT.PlayerState;
|
||||
|
||||
window.onTouchBasedDevice = function () {
|
||||
return navigator.userAgent.match(/iPhone|iPod|iPad/i);
|
||||
};
|
||||
|
||||
jasmine.stubbedCaption = {
|
||||
end: [
|
||||
3120, 6270, 8490, 21620, 24920, 25750, 27900, 34380, 35550, 40250
|
||||
],
|
||||
start: [
|
||||
1180, 3120, 6270, 14910, 21620, 24920, 25750, 27900, 34380, 35550
|
||||
],
|
||||
text: [
|
||||
'MICHAEL CIMA: So let\'s do the first one here.',
|
||||
'Vacancies, where do they come from?',
|
||||
'Well, imagine a perfect crystal.',
|
||||
'Now we know at any temperature other than absolute zero ' +
|
||||
'there\'s enough',
|
||||
'energy going around that some atoms will have more energy',
|
||||
'than others, right?',
|
||||
'There\'s a distribution.',
|
||||
'If I plot energy here and number, these atoms in the crystal ' +
|
||||
'will have a',
|
||||
'distribution of energy.',
|
||||
'And some will have quite a bit of energy, just for a moment.'
|
||||
]
|
||||
};
|
||||
|
||||
// For our purposes, we need to make sure that the function
|
||||
// $.ajaxWithPrefix does not fail when during tests a captions file is
|
||||
// requested. It is originally defined in file:
|
||||
//
|
||||
// common/static/coffee/src/ajax_prefix.js
|
||||
//
|
||||
// We will replace it with a function that does:
|
||||
//
|
||||
// 1.) Return a hard coded captions object if the file name contains
|
||||
// 'Z5KLxerq05Y'.
|
||||
// 2.) Behaves the same a as the original function in all other cases.
|
||||
$.ajaxWithPrefix = function (url, settings) {
|
||||
var data, success;
|
||||
|
||||
if (!settings) {
|
||||
settings = url;
|
||||
url = settings.url;
|
||||
success = settings.success;
|
||||
data = settings.data;
|
||||
}
|
||||
|
||||
if (
|
||||
url.match(/Z5KLxerq05Y/g) ||
|
||||
url.match(/7tqY6eQzVhE/g) ||
|
||||
url.match(/cogebirgzzM/g)
|
||||
) {
|
||||
if ($.isFunction(success)) {
|
||||
return success(jasmine.stubbedCaption);
|
||||
} else if ($.isFunction(data)) {
|
||||
return data(jasmine.stubbedCaption);
|
||||
}
|
||||
} else {
|
||||
return oldAjaxWithPrefix.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
// Time waitsFor() should wait for before failing a test.
|
||||
window.WAIT_TIMEOUT = 5000;
|
||||
|
||||
jasmine.getFixtures().fixturesPath += 'fixtures';
|
||||
|
||||
jasmine.stubbedMetadata = {
|
||||
'7tqY6eQzVhE': {
|
||||
id: '7tqY6eQzVhE',
|
||||
duration: 300
|
||||
},
|
||||
'cogebirgzzM': {
|
||||
id: 'cogebirgzzM',
|
||||
duration: 200
|
||||
},
|
||||
bogus: {
|
||||
duration: 100
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.fireEvent = function (el, eventName) {
|
||||
var event;
|
||||
|
||||
if (document.createEvent) {
|
||||
event = document.createEvent('HTMLEvents');
|
||||
event.initEvent(eventName, true, true);
|
||||
} else {
|
||||
event = document.createEventObject();
|
||||
event.eventType = eventName;
|
||||
}
|
||||
|
||||
event.eventName = eventName;
|
||||
|
||||
if (document.createEvent) {
|
||||
el.dispatchEvent(event);
|
||||
} else {
|
||||
el.fireEvent('on' + event.eventType, event);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.stubbedHtml5Speeds = ['0.75', '1.0', '1.25', '1.50'];
|
||||
|
||||
jasmine.stubRequests = function () {
|
||||
return spyOn($, 'ajax').andCallFake(function (settings) {
|
||||
var match, status, callCallback;
|
||||
|
||||
if (
|
||||
match = settings.url
|
||||
.match(/youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/)
|
||||
) {
|
||||
status = match[1].split('_');
|
||||
if (status && status[0] === 'status') {
|
||||
callCallback = function (callback) {
|
||||
callback.call(window, {}, status[1]);
|
||||
};
|
||||
|
||||
return {
|
||||
always: callCallback,
|
||||
error: callCallback,
|
||||
done: callCallback
|
||||
};
|
||||
} else if (settings.success) {
|
||||
return settings.success({
|
||||
data: jasmine.stubbedMetadata[match[1]]
|
||||
});
|
||||
} else {
|
||||
return {
|
||||
always: function (callback) {
|
||||
return callback.call(window, {}, 'success');
|
||||
},
|
||||
done: function (callback) {
|
||||
return callback.call(window, {}, 'success');
|
||||
}
|
||||
};
|
||||
}
|
||||
} else if (
|
||||
match = settings.url
|
||||
.match(/static(\/.*)?\/subs\/(.+)\.srt\.sjson/)
|
||||
) {
|
||||
return settings.success(jasmine.stubbedCaption);
|
||||
} else if (settings.url.match(/.+\/problem_get$/)) {
|
||||
return settings.success({
|
||||
html: readFixtures('problem_content.html')
|
||||
});
|
||||
} else if (
|
||||
settings.url === '/calculate' ||
|
||||
settings.url.match(/.+\/goto_position$/) ||
|
||||
settings.url.match(/event$/) ||
|
||||
settings.url.match(/.+\/problem_(check|reset|show|save)$/)
|
||||
) {
|
||||
// Do nothing.
|
||||
} else {
|
||||
throw 'External request attempted for ' +
|
||||
settings.url +
|
||||
', which is not defined.';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Add custom Jasmine matchers.
|
||||
beforeEach(function () {
|
||||
this.addMatchers({
|
||||
toHaveAttrs: function (attrs) {
|
||||
var element = this.actual,
|
||||
result = true;
|
||||
|
||||
if ($.isEmptyObject(attrs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$.each(attrs, function (name, value) {
|
||||
return result = result && element.attr(name) === value;
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
toBeInRange: function (min, max) {
|
||||
return min <= this.actual && this.actual <= max;
|
||||
},
|
||||
toBeInArray: function (array) {
|
||||
return $.inArray(this.actual, array) > -1;
|
||||
}
|
||||
});
|
||||
|
||||
return this.addMatchers(imagediff.jasmine);
|
||||
});
|
||||
|
||||
// Stub jQuery.cookie module.
|
||||
$.cookie = jasmine.createSpy('jQuery.cookie').andReturn('1.0');
|
||||
|
||||
// # Stub jQuery.qtip module.
|
||||
$.fn.qtip = jasmine.createSpy('jQuery.qtip');
|
||||
|
||||
// Stub jQuery.scrollTo module.
|
||||
$.fn.scrollTo = jasmine.createSpy('jQuery.scrollTo');
|
||||
|
||||
jasmine.initializePlayer = function (fixture, params) {
|
||||
var state;
|
||||
|
||||
if (_.isString(fixture)) {
|
||||
// `fixture` is a name of a fixture file.
|
||||
loadFixtures(fixture);
|
||||
} else {
|
||||
// `fixture` is not a string. The first parameter is an object?
|
||||
if (_.isObject(fixture)) {
|
||||
// The first parameter contains attributes for the main video
|
||||
// DIV element.
|
||||
params = fixture;
|
||||
}
|
||||
|
||||
// "video_all.html" is the default HTML template for HTML5 video.
|
||||
loadFixtures('video_all.html');
|
||||
}
|
||||
|
||||
// If `params` is an object, assign it's properties as data attributes
|
||||
// to the main video DIV element.
|
||||
if (_.isObject(params)) {
|
||||
$('#example')
|
||||
.find('#video_id')
|
||||
.data(params);
|
||||
}
|
||||
|
||||
state = new Video('#example');
|
||||
|
||||
state.resizer = (function () {
|
||||
var methods = [
|
||||
'align',
|
||||
'alignByWidthOnly',
|
||||
'alignByHeightOnly',
|
||||
'setParams',
|
||||
'setMode'
|
||||
],
|
||||
obj = {};
|
||||
|
||||
$.each(methods, function (index, method) {
|
||||
obj[method] = jasmine.createSpy(method).andReturn(obj);
|
||||
});
|
||||
|
||||
return obj;
|
||||
}());
|
||||
|
||||
// We return the `state` object of the newly initialized Video.
|
||||
return state;
|
||||
};
|
||||
|
||||
jasmine.initializePlayerYouTube = function () {
|
||||
// "video.html" contains HTML template for a YouTube video.
|
||||
return jasmine.initializePlayer('video.html');
|
||||
};
|
||||
}).call(this, window.jQuery);
|
||||
@@ -1,165 +1,108 @@
|
||||
(function () {
|
||||
(function (undefined) {
|
||||
describe('VideoPlayer Events', function () {
|
||||
var state, videoPlayer, player, videoControl, videoCaption,
|
||||
videoProgressSlider, videoSpeedControl, videoVolumeControl,
|
||||
oldOTBD;
|
||||
var state, oldOTBD;
|
||||
|
||||
function initialize(fixture, params) {
|
||||
if (_.isString(fixture)) {
|
||||
loadFixtures(fixture);
|
||||
} else {
|
||||
if (_.isObject(fixture)) {
|
||||
params = fixture;
|
||||
}
|
||||
describe('HTML5', function () {
|
||||
beforeEach(function () {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine
|
||||
.createSpy('onTouchBasedDevice')
|
||||
.andReturn(null);
|
||||
|
||||
loadFixtures('video_all.html');
|
||||
}
|
||||
jasmine.stubRequests();
|
||||
|
||||
if (_.isObject(params)) {
|
||||
$('#example')
|
||||
.find('#video_id')
|
||||
.data(params);
|
||||
}
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state = new Video('#example');
|
||||
state.videoEl = $('video, iframe');
|
||||
});
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
videoPlayer = state.videoPlayer;
|
||||
player = videoPlayer.player;
|
||||
videoControl = state.videoControl;
|
||||
videoCaption = state.videoCaption;
|
||||
videoProgressSlider = state.videoProgressSlider;
|
||||
videoSpeedControl = state.videoSpeedControl;
|
||||
videoVolumeControl = state.videoVolumeControl;
|
||||
afterEach(function () {
|
||||
$('source').remove();
|
||||
window.onTouchBasedDevice = oldOTBD;
|
||||
});
|
||||
|
||||
state.resizer = (function () {
|
||||
var methods = [
|
||||
'align',
|
||||
'alignByWidthOnly',
|
||||
'alignByHeightOnly',
|
||||
'setParams',
|
||||
'setMode'
|
||||
],
|
||||
obj = {};
|
||||
it('initialize', function () {
|
||||
waitsFor(function () {
|
||||
return state.el.hasClass('is-initialized');
|
||||
}, 'Player is not initialized.', WAIT_TIMEOUT);
|
||||
|
||||
$.each(methods, function (index, method) {
|
||||
obj[method] = jasmine.createSpy(method).andReturn(obj);
|
||||
runs(function () {
|
||||
expect('initialize').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
});
|
||||
|
||||
it('ready', function () {
|
||||
waitsFor(function () {
|
||||
return state.el.hasClass('is-initialized');
|
||||
}, 'Player is not initialized.', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect('ready').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
});
|
||||
|
||||
it('play', function () {
|
||||
state.videoPlayer.play();
|
||||
expect('play').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
|
||||
it('pause', function () {
|
||||
state.videoPlayer.play();
|
||||
state.videoPlayer.pause();
|
||||
expect('pause').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
|
||||
it('volumechange', function () {
|
||||
state.videoPlayer.onVolumeChange(60);
|
||||
|
||||
expect('volumechange').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
|
||||
it('speedchange', function () {
|
||||
state.videoPlayer.onSpeedChange('2.0');
|
||||
|
||||
expect('speedchange').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
|
||||
it('seek', function () {
|
||||
state.videoPlayer.onCaptionSeek({
|
||||
time: 1,
|
||||
type: 'any'
|
||||
});
|
||||
|
||||
return obj;
|
||||
}());
|
||||
}
|
||||
|
||||
function initializeYouTube() {
|
||||
initialize('video.html');
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice')
|
||||
.andReturn(null);
|
||||
this.oldYT = window.YT;
|
||||
|
||||
jasmine.stubRequests();
|
||||
window.YT = {
|
||||
Player: function () {
|
||||
return {
|
||||
getPlaybackQuality: function () {},
|
||||
getDuration: function () { return 60; }
|
||||
};
|
||||
},
|
||||
PlayerState: this.oldYT.PlayerState,
|
||||
ready: function (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
$('source').remove();
|
||||
window.onTouchBasedDevice = oldOTBD;
|
||||
window.YT = this.oldYT;
|
||||
});
|
||||
|
||||
it('initialize', function(){
|
||||
runs(function () {
|
||||
initialize();
|
||||
expect('seek').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return state.el.hasClass('is-initialized');
|
||||
}, 'Player is not initialized.', WAIT_TIMEOUT);
|
||||
it('ended', function () {
|
||||
state.videoPlayer.onEnded();
|
||||
|
||||
runs(function () {
|
||||
expect('initialize').not.toHaveBeenTriggeredOn('.video');
|
||||
expect('ended').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
});
|
||||
|
||||
it('ready', function() {
|
||||
runs(function () {
|
||||
initialize();
|
||||
describe('YouTube', function () {
|
||||
beforeEach(function () {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine
|
||||
.createSpy('onTouchBasedDevice')
|
||||
.andReturn(null);
|
||||
|
||||
jasmine.stubRequests();
|
||||
|
||||
state = jasmine.initializePlayerYouTube();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return state.el.hasClass('is-initialized');
|
||||
}, 'Player is not initialized.', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect('ready').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
});
|
||||
|
||||
it('play', function() {
|
||||
initialize();
|
||||
videoPlayer.play();
|
||||
expect('play').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
|
||||
it('pause', function() {
|
||||
initialize();
|
||||
videoPlayer.play();
|
||||
videoPlayer.pause();
|
||||
expect('pause').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
|
||||
it('volumechange', function() {
|
||||
initialize();
|
||||
videoPlayer.onVolumeChange(60);
|
||||
|
||||
expect('volumechange').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
|
||||
it('speedchange', function() {
|
||||
initialize();
|
||||
videoPlayer.onSpeedChange('2.0');
|
||||
|
||||
expect('speedchange').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
|
||||
it('qualitychange', function() {
|
||||
initializeYouTube();
|
||||
videoPlayer.onPlaybackQualityChange();
|
||||
|
||||
expect('qualitychange').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
|
||||
it('seek', function() {
|
||||
initialize();
|
||||
videoPlayer.onCaptionSeek({
|
||||
time: 1,
|
||||
type: 'any'
|
||||
afterEach(function () {
|
||||
$('source').remove();
|
||||
window.onTouchBasedDevice = oldOTBD;
|
||||
});
|
||||
|
||||
expect('seek').not.toHaveBeenTriggeredOn('.video');
|
||||
it('qualitychange', function () {
|
||||
state.videoPlayer.onPlaybackQualityChange();
|
||||
|
||||
expect('qualitychange').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
});
|
||||
|
||||
it('ended', function() {
|
||||
initialize();
|
||||
videoPlayer.onEnded();
|
||||
|
||||
expect('ended').not.toHaveBeenTriggeredOn('.video');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(function () {
|
||||
(function (undefined) {
|
||||
describe('Video', function () {
|
||||
var oldOTBD;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
window.OldVideoPlayer = undefined;
|
||||
$('source').remove();
|
||||
});
|
||||
|
||||
@@ -30,10 +29,6 @@
|
||||
expect(this.state.videoType).toEqual('youtube');
|
||||
});
|
||||
|
||||
it('reset the current video player', function () {
|
||||
expect(window.OldVideoPlayer).toBeUndefined();
|
||||
});
|
||||
|
||||
it('set the elements', function () {
|
||||
expect(this.state.el).toBe('#video_id');
|
||||
});
|
||||
@@ -76,10 +71,6 @@
|
||||
expect(state.videoType).toEqual('html5');
|
||||
});
|
||||
|
||||
it('reset the current video player', function () {
|
||||
expect(window.OldVideoPlayer).toBeUndefined();
|
||||
});
|
||||
|
||||
it('set the elements', function () {
|
||||
expect(state.el).toBe('#video_id');
|
||||
});
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
(function () {
|
||||
(function (undefined) {
|
||||
describe('Video HTML5Video', function () {
|
||||
var state, player, oldOTBD, playbackRates = [0.75, 1.0, 1.25, 1.5];
|
||||
|
||||
function initialize() {
|
||||
loadFixtures('video_html5.html');
|
||||
state = new Video('#example');
|
||||
player = state.videoPlayer.player;
|
||||
}
|
||||
var state, oldOTBD, playbackRates = [0.75, 1.0, 1.25, 1.5];
|
||||
|
||||
beforeEach(function () {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
@@ -14,7 +8,7 @@
|
||||
.createSpy('onTouchBasedDevice').andReturn(null);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
afterEach(function () {
|
||||
state = undefined;
|
||||
$.fn.scrollTo.reset();
|
||||
$('.subtitles').remove();
|
||||
@@ -24,48 +18,46 @@
|
||||
|
||||
describe('on non-Touch devices', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
player.config.events.onReady = jasmine.createSpy('onReady');
|
||||
state = jasmine.initializePlayer('video_html5.html');
|
||||
|
||||
state.videoPlayer.player.config.events.onReady = jasmine.createSpy('onReady');
|
||||
});
|
||||
|
||||
describe('events:', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(player, 'callStateChangeCallback').andCallThrough();
|
||||
spyOn(state.videoPlayer.player, 'callStateChangeCallback').andCallThrough();
|
||||
});
|
||||
|
||||
describe('[click]', function () {
|
||||
describe('when player is paused', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(player.video, 'play').andCallThrough();
|
||||
player.playerState = STATUS.PAUSED;
|
||||
$(player.videoEl).trigger('click');
|
||||
spyOn(state.videoPlayer.player.video, 'play').andCallThrough();
|
||||
state.videoPlayer.player.playerState = STATUS.PAUSED;
|
||||
$(state.videoPlayer.player.videoEl).trigger('click');
|
||||
});
|
||||
|
||||
it('native play event was called', function () {
|
||||
expect(player.video.play).toHaveBeenCalled();
|
||||
expect(state.videoPlayer.player.video.play).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('player state was changed', function () {
|
||||
waitsFor(function () {
|
||||
return player.getPlayerState() !== STATUS.PAUSED;
|
||||
return state.videoPlayer.player.getPlayerState() !== STATUS.PAUSED;
|
||||
}, 'Player state should be changed', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(player.getPlayerState())
|
||||
expect(state.videoPlayer.player.getPlayerState())
|
||||
.toBe(STATUS.PLAYING);
|
||||
});
|
||||
});
|
||||
|
||||
it('callback was called', function () {
|
||||
waitsFor(function () {
|
||||
var stateStatus = state.videoPlayer.player
|
||||
.getPlayerState();
|
||||
|
||||
return stateStatus !== STATUS.PAUSED;
|
||||
return state.videoPlayer.player.getPlayerState() !== STATUS.PAUSED;
|
||||
}, 'Player state should be changed', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(player.callStateChangeCallback)
|
||||
expect(state.videoPlayer.player.callStateChangeCallback)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -73,33 +65,33 @@
|
||||
|
||||
describe('[player is playing]', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(player.video, 'pause').andCallThrough();
|
||||
player.playerState = STATUS.PLAYING;
|
||||
$(player.videoEl).trigger('click');
|
||||
spyOn(state.videoPlayer.player.video, 'pause').andCallThrough();
|
||||
state.videoPlayer.player.playerState = STATUS.PLAYING;
|
||||
$(state.videoPlayer.player.videoEl).trigger('click');
|
||||
});
|
||||
|
||||
it('native event was called', function () {
|
||||
expect(player.video.pause).toHaveBeenCalled();
|
||||
expect(state.videoPlayer.player.video.pause).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('player state was changed', function () {
|
||||
waitsFor(function () {
|
||||
return player.getPlayerState() !== STATUS.PLAYING;
|
||||
return state.videoPlayer.player.getPlayerState() !== STATUS.PLAYING;
|
||||
}, 'Player state should be changed', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(player.getPlayerState())
|
||||
expect(state.videoPlayer.player.getPlayerState())
|
||||
.toBe(STATUS.PAUSED);
|
||||
});
|
||||
});
|
||||
|
||||
it('callback was called', function () {
|
||||
waitsFor(function () {
|
||||
return player.getPlayerState() !== STATUS.PLAYING;
|
||||
return state.videoPlayer.player.getPlayerState() !== STATUS.PLAYING;
|
||||
}, 'Player state should be changed', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(player.callStateChangeCallback)
|
||||
expect(state.videoPlayer.player.callStateChangeCallback)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -108,37 +100,34 @@
|
||||
|
||||
describe('[play]', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(player.video, 'play').andCallThrough();
|
||||
player.playerState = STATUS.PAUSED;
|
||||
player.playVideo();
|
||||
spyOn(state.videoPlayer.player.video, 'play').andCallThrough();
|
||||
state.videoPlayer.player.playerState = STATUS.PAUSED;
|
||||
state.videoPlayer.player.playVideo();
|
||||
});
|
||||
|
||||
it('native event was called', function () {
|
||||
expect(player.video.play).toHaveBeenCalled();
|
||||
expect(state.videoPlayer.player.video.play).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('player state was changed', function () {
|
||||
waitsFor(function () {
|
||||
var state = player.getPlayerState();
|
||||
|
||||
return state !== STATUS.PAUSED;
|
||||
return state.videoPlayer.player.getPlayerState() !== STATUS.PAUSED;
|
||||
}, 'Player state should be changed', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(player.getPlayerState()).toBe(STATUS.PLAYING);
|
||||
expect(state.videoPlayer.player.getPlayerState())
|
||||
.toBe(STATUS.PLAYING);
|
||||
});
|
||||
});
|
||||
|
||||
it('callback was called', function () {
|
||||
waitsFor(function () {
|
||||
var state = player.getPlayerState();
|
||||
|
||||
return state !== STATUS.PAUSED;
|
||||
return state.videoPlayer.player.getPlayerState() !== STATUS.PAUSED;
|
||||
}, 'Player state should be changed', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(player.callStateChangeCallback)
|
||||
expect(state.videoPlayer.player.callStateChangeCallback)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -146,35 +135,36 @@
|
||||
|
||||
describe('[pause]', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(player.video, 'pause').andCallThrough();
|
||||
player.playerState = STATUS.UNSTARTED;
|
||||
player.playVideo();
|
||||
spyOn(state.videoPlayer.player.video, 'pause').andCallThrough();
|
||||
state.videoPlayer.player.playerState = STATUS.UNSTARTED;
|
||||
state.videoPlayer.player.playVideo();
|
||||
waitsFor(function () {
|
||||
return player.getPlayerState() !== STATUS.UNSTARTED;
|
||||
return state.videoPlayer.player.getPlayerState() !== STATUS.UNSTARTED;
|
||||
}, 'Video never started playing', WAIT_TIMEOUT);
|
||||
player.pauseVideo();
|
||||
state.videoPlayer.player.pauseVideo();
|
||||
});
|
||||
|
||||
it('native event was called', function () {
|
||||
expect(player.video.pause).toHaveBeenCalled();
|
||||
expect(state.videoPlayer.player.video.pause).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('player state was changed', function () {
|
||||
waitsFor(function () {
|
||||
return player.getPlayerState() !== STATUS.PLAYING;
|
||||
return state.videoPlayer.player.getPlayerState() !== STATUS.PLAYING;
|
||||
}, 'Player state should be changed', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(player.getPlayerState()).toBe(STATUS.PAUSED);
|
||||
expect(state.videoPlayer.player.getPlayerState())
|
||||
.toBe(STATUS.PAUSED);
|
||||
});
|
||||
});
|
||||
|
||||
it('callback was called', function () {
|
||||
waitsFor(function () {
|
||||
return player.getPlayerState() !== STATUS.PLAYING;
|
||||
return state.videoPlayer.player.getPlayerState() !== STATUS.PLAYING;
|
||||
}, 'Player state should be changed', WAIT_TIMEOUT);
|
||||
runs(function () {
|
||||
expect(player.callStateChangeCallback)
|
||||
expect(state.videoPlayer.player.callStateChangeCallback)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -186,13 +176,14 @@
|
||||
'onReady called', function ()
|
||||
{
|
||||
waitsFor(function () {
|
||||
return player.getPlayerState() !== STATUS.UNSTARTED;
|
||||
return state.videoPlayer.player.getPlayerState() !== STATUS.UNSTARTED;
|
||||
}, 'Video cannot be played', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(player.getPlayerState()).toBe(STATUS.PAUSED);
|
||||
expect(player.video.currentTime).toBe(0);
|
||||
expect(player.config.events.onReady)
|
||||
expect(state.videoPlayer.player.getPlayerState())
|
||||
.toBe(STATUS.PAUSED);
|
||||
expect(state.videoPlayer.player.video.currentTime).toBe(0);
|
||||
expect(state.videoPlayer.player.config.events.onReady)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -201,20 +192,21 @@
|
||||
describe('[ended]', function () {
|
||||
beforeEach(function () {
|
||||
waitsFor(function () {
|
||||
return player.getPlayerState() !== STATUS.UNSTARTED;
|
||||
return state.videoPlayer.player.getPlayerState() !== STATUS.UNSTARTED;
|
||||
}, 'Video cannot be played', WAIT_TIMEOUT);
|
||||
});
|
||||
|
||||
it('player state was changed', function () {
|
||||
runs(function () {
|
||||
jasmine.fireEvent(player.video, 'ended');
|
||||
expect(player.getPlayerState()).toBe(STATUS.ENDED);
|
||||
jasmine.fireEvent(state.videoPlayer.player.video, 'ended');
|
||||
expect(state.videoPlayer.player.getPlayerState()).toBe(STATUS.ENDED);
|
||||
});
|
||||
});
|
||||
|
||||
it('callback was called', function () {
|
||||
jasmine.fireEvent(player.video, 'ended');
|
||||
expect(player.callStateChangeCallback).toHaveBeenCalled();
|
||||
jasmine.fireEvent(state.videoPlayer.player.video, 'ended');
|
||||
expect(state.videoPlayer.player.callStateChangeCallback)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -224,36 +216,36 @@
|
||||
|
||||
beforeEach(function () {
|
||||
waitsFor(function () {
|
||||
volume = player.video.volume;
|
||||
seek = player.video.currentTime;
|
||||
return player.playerState === STATUS.PAUSED;
|
||||
volume = state.videoPlayer.player.video.volume;
|
||||
seek = state.videoPlayer.player.video.currentTime;
|
||||
return state.videoPlayer.player.playerState === STATUS.PAUSED;
|
||||
}, 'Video cannot be played', WAIT_TIMEOUT);
|
||||
});
|
||||
|
||||
it('pauseVideo', function () {
|
||||
runs(function () {
|
||||
spyOn(player.video, 'pause').andCallThrough();
|
||||
player.pauseVideo();
|
||||
expect(player.video.pause).toHaveBeenCalled();
|
||||
spyOn(state.videoPlayer.player.video, 'pause').andCallThrough();
|
||||
state.videoPlayer.player.pauseVideo();
|
||||
expect(state.videoPlayer.player.video.pause).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('seekTo', function () {
|
||||
it('set new correct value', function () {
|
||||
runs(function () {
|
||||
player.seekTo(2);
|
||||
expect(player.getCurrentTime()).toBe(2);
|
||||
state.videoPlayer.player.seekTo(2);
|
||||
expect(state.videoPlayer.player.getCurrentTime()).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
it('set new inccorrect values', function () {
|
||||
runs(function () {
|
||||
player.seekTo(-50);
|
||||
expect(player.getCurrentTime()).toBe(seek);
|
||||
player.seekTo('5');
|
||||
expect(player.getCurrentTime()).toBe(seek);
|
||||
player.seekTo(500000);
|
||||
expect(player.getCurrentTime()).toBe(seek);
|
||||
state.videoPlayer.player.seekTo(-50);
|
||||
expect(state.videoPlayer.player.getCurrentTime()).toBe(seek);
|
||||
state.videoPlayer.player.seekTo('5');
|
||||
expect(state.videoPlayer.player.getCurrentTime()).toBe(seek);
|
||||
state.videoPlayer.player.seekTo(500000);
|
||||
expect(state.videoPlayer.player.getCurrentTime()).toBe(seek);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -261,88 +253,89 @@
|
||||
describe('setVolume', function () {
|
||||
it('set new correct value', function () {
|
||||
runs(function () {
|
||||
player.setVolume(50);
|
||||
expect(player.getVolume()).toBe(50 * 0.01);
|
||||
state.videoPlayer.player.setVolume(50);
|
||||
expect(state.videoPlayer.player.getVolume()).toBe(50 * 0.01);
|
||||
});
|
||||
});
|
||||
|
||||
it('set new incorrect values', function () {
|
||||
runs(function () {
|
||||
player.setVolume(-50);
|
||||
expect(player.getVolume()).toBe(volume);
|
||||
player.setVolume('5');
|
||||
expect(player.getVolume()).toBe(volume);
|
||||
player.setVolume(500000);
|
||||
expect(player.getVolume()).toBe(volume);
|
||||
state.videoPlayer.player.setVolume(-50);
|
||||
expect(state.videoPlayer.player.getVolume()).toBe(volume);
|
||||
state.videoPlayer.player.setVolume('5');
|
||||
expect(state.videoPlayer.player.getVolume()).toBe(volume);
|
||||
state.videoPlayer.player.setVolume(500000);
|
||||
expect(state.videoPlayer.player.getVolume()).toBe(volume);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('getCurrentTime', function () {
|
||||
runs(function () {
|
||||
player.video.currentTime = 3;
|
||||
expect(player.getCurrentTime())
|
||||
.toBe(player.video.currentTime);
|
||||
state.videoPlayer.player.video.currentTime = 3;
|
||||
expect(state.videoPlayer.player.getCurrentTime())
|
||||
.toBe(state.videoPlayer.player.video.currentTime);
|
||||
});
|
||||
});
|
||||
|
||||
it('playVideo', function () {
|
||||
runs(function () {
|
||||
spyOn(player.video, 'play').andCallThrough();
|
||||
player.playVideo();
|
||||
expect(player.video.play).toHaveBeenCalled();
|
||||
spyOn(state.videoPlayer.player.video, 'play').andCallThrough();
|
||||
state.videoPlayer.player.playVideo();
|
||||
expect(state.videoPlayer.player.video.play).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('getPlayerState', function () {
|
||||
runs(function () {
|
||||
player.playerState = STATUS.PLAYING;
|
||||
expect(player.getPlayerState()).toBe(STATUS.PLAYING);
|
||||
player.playerState = STATUS.ENDED;
|
||||
expect(player.getPlayerState()).toBe(STATUS.ENDED);
|
||||
state.videoPlayer.player.playerState = STATUS.PLAYING;
|
||||
expect(state.videoPlayer.player.getPlayerState()).toBe(STATUS.PLAYING);
|
||||
state.videoPlayer.player.playerState = STATUS.ENDED;
|
||||
expect(state.videoPlayer.player.getPlayerState()).toBe(STATUS.ENDED);
|
||||
});
|
||||
});
|
||||
|
||||
it('getVolume', function () {
|
||||
runs(function () {
|
||||
volume = player.video.volume = 0.5;
|
||||
expect(player.getVolume()).toBe(volume);
|
||||
volume = state.videoPlayer.player.video.volume = 0.5;
|
||||
expect(state.videoPlayer.player.getVolume()).toBe(volume);
|
||||
});
|
||||
});
|
||||
|
||||
it('getDuration', function () {
|
||||
runs(function () {
|
||||
duration = player.video.duration;
|
||||
expect(player.getDuration()).toBe(duration);
|
||||
duration = state.videoPlayer.player.video.duration;
|
||||
expect(state.videoPlayer.player.getDuration()).toBe(duration);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setPlaybackRate', function () {
|
||||
it('set a correct value', function () {
|
||||
playbackRate = 1.5;
|
||||
player.setPlaybackRate(playbackRate);
|
||||
expect(player.video.playbackRate).toBe(playbackRate);
|
||||
state.videoPlayer.player.setPlaybackRate(playbackRate);
|
||||
expect(state.videoPlayer.player.video.playbackRate).toBe(playbackRate);
|
||||
});
|
||||
|
||||
it('set NaN value', function () {
|
||||
var oldPlaybackRate = player.video.playbackRate;
|
||||
var oldPlaybackRate = state.videoPlayer.player.video.playbackRate;
|
||||
|
||||
// When we try setting the playback rate to some
|
||||
// non-numerical value, nothing should happen.
|
||||
playbackRate = NaN;
|
||||
player.setPlaybackRate(playbackRate);
|
||||
expect(player.video.playbackRate).toBe(oldPlaybackRate);
|
||||
state.videoPlayer.player.setPlaybackRate(playbackRate);
|
||||
expect(state.videoPlayer.player.video.playbackRate)
|
||||
.toBe(oldPlaybackRate);
|
||||
});
|
||||
});
|
||||
|
||||
it('getAvailablePlaybackRates', function () {
|
||||
expect(player.getAvailablePlaybackRates())
|
||||
expect(state.videoPlayer.player.getAvailablePlaybackRates())
|
||||
.toEqual(playbackRates);
|
||||
});
|
||||
|
||||
it('_getLogs', function () {
|
||||
runs(function () {
|
||||
var logs = player._getLogs();
|
||||
var logs = state.videoPlayer.player._getLogs();
|
||||
expect(logs).toEqual(jasmine.any(Array));
|
||||
expect(logs.length).toBeGreaterThan(0);
|
||||
});
|
||||
@@ -352,8 +345,10 @@
|
||||
|
||||
it('native controls are used on iPhone', function () {
|
||||
window.onTouchBasedDevice.andReturn(['iPhone']);
|
||||
initialize();
|
||||
player.config.events.onReady = jasmine.createSpy('onReady');
|
||||
|
||||
state = jasmine.initializePlayer('video_html5.html');
|
||||
|
||||
state.videoPlayer.player.config.events.onReady = jasmine.createSpy('onReady');
|
||||
|
||||
expect($('video')).toHaveAttr('controls');
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(function (requirejs, require, define) {
|
||||
(function (requirejs, require, define, undefined) {
|
||||
|
||||
require(
|
||||
['video/00_resizer.js'],
|
||||
@@ -104,7 +104,7 @@ function (Resizer) {
|
||||
beforeEach(function () {
|
||||
var spiesCount = _.range(3);
|
||||
|
||||
spiesList = $.map(spiesCount, function() {
|
||||
spiesList = $.map(spiesCount, function () {
|
||||
return jasmine.createSpy();
|
||||
});
|
||||
|
||||
@@ -113,13 +113,13 @@ function (Resizer) {
|
||||
|
||||
|
||||
it('callbacks are called', function () {
|
||||
$.each(spiesList, function(index, spy) {
|
||||
$.each(spiesList, function (index, spy) {
|
||||
resizer.callbacks.add(spy);
|
||||
});
|
||||
|
||||
resizer.align();
|
||||
|
||||
$.each(spiesList, function(index, spy) {
|
||||
$.each(spiesList, function (index, spy) {
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -135,20 +135,20 @@ function (Resizer) {
|
||||
});
|
||||
|
||||
it('All callbacks are removed', function () {
|
||||
$.each(spiesList, function(index, spy) {
|
||||
$.each(spiesList, function (index, spy) {
|
||||
resizer.callbacks.add(spy);
|
||||
});
|
||||
|
||||
resizer.callbacks.removeAll();
|
||||
resizer.align();
|
||||
|
||||
$.each(spiesList, function(index, spy) {
|
||||
$.each(spiesList, function (index, spy) {
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('Specific callback is removed', function () {
|
||||
$.each(spiesList, function(index, spy) {
|
||||
$.each(spiesList, function (index, spy) {
|
||||
resizer.callbacks.add(spy);
|
||||
});
|
||||
|
||||
@@ -158,14 +158,17 @@ function (Resizer) {
|
||||
expect(spiesList[1]).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Error message is shown when wrong argument type is passed', function () {
|
||||
it(
|
||||
'Error message is shown when wrong argument type is passed',
|
||||
function ()
|
||||
{
|
||||
var methods = ['add', 'once'],
|
||||
errorMessage = 'TypeError: Argument is not a function.',
|
||||
arg = {};
|
||||
|
||||
spyOn(console, 'error');
|
||||
|
||||
$.each(methods, function(index, methodName) {
|
||||
$.each(methods, function (index, methodName) {
|
||||
resizer.callbacks[methodName](arg);
|
||||
expect(console.error).toHaveBeenCalledWith(errorMessage);
|
||||
//reset spy
|
||||
|
||||
@@ -1,26 +1,20 @@
|
||||
(function () {
|
||||
(function (undefined) {
|
||||
describe('VideoCaption', function () {
|
||||
var state, videoPlayer, videoCaption, videoSpeedControl, oldOTBD;
|
||||
|
||||
function initialize() {
|
||||
loadFixtures('video_all.html');
|
||||
state = new Video('#example');
|
||||
videoPlayer = state.videoPlayer;
|
||||
videoCaption = state.videoCaption;
|
||||
videoSpeedControl = state.videoSpeedControl;
|
||||
videoControl = state.videoControl;
|
||||
$.fn.scrollTo.reset();
|
||||
}
|
||||
var state, oldOTBD;
|
||||
|
||||
beforeEach(function () {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice')
|
||||
.andReturn(null);
|
||||
initialize();
|
||||
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
videoControl = state.videoControl;
|
||||
|
||||
$.fn.scrollTo.reset();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
YT.Player = undefined;
|
||||
$('.subtitles').remove();
|
||||
|
||||
// `source` tags should be removed to avoid memory leak bug that we
|
||||
@@ -35,7 +29,12 @@
|
||||
describe('always', function () {
|
||||
beforeEach(function () {
|
||||
spyOn($, 'ajaxWithPrefix').andCallThrough();
|
||||
initialize();
|
||||
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
videoControl = state.videoControl;
|
||||
|
||||
$.fn.scrollTo.reset();
|
||||
});
|
||||
|
||||
it('create the caption element', function () {
|
||||
@@ -57,7 +56,7 @@
|
||||
|
||||
it('fetch the caption', function () {
|
||||
waitsFor(function () {
|
||||
if (videoCaption.loaded === true) {
|
||||
if (state.videoCaption.loaded === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -66,7 +65,7 @@
|
||||
|
||||
runs(function () {
|
||||
expect($.ajaxWithPrefix).toHaveBeenCalledWith({
|
||||
url: videoCaption.captionURL(),
|
||||
url: state.videoCaption.captionURL(),
|
||||
notifyOnError: false,
|
||||
success: jasmine.any(Function),
|
||||
error: jasmine.any(Function)
|
||||
@@ -76,37 +75,37 @@
|
||||
|
||||
it('bind window resize event', function () {
|
||||
expect($(window)).toHandleWith(
|
||||
'resize', videoCaption.resize
|
||||
'resize', state.videoCaption.resize
|
||||
);
|
||||
});
|
||||
|
||||
it('bind the hide caption button', function () {
|
||||
expect($('.hide-subtitles')).toHandleWith(
|
||||
'click', videoCaption.toggle
|
||||
'click', state.videoCaption.toggle
|
||||
);
|
||||
});
|
||||
|
||||
it('bind the mouse movement', function () {
|
||||
expect($('.subtitles')).toHandleWith(
|
||||
'mouseover', videoCaption.onMouseEnter
|
||||
'mouseover', state.videoCaption.onMouseEnter
|
||||
);
|
||||
expect($('.subtitles')).toHandleWith(
|
||||
'mouseout', videoCaption.onMouseLeave
|
||||
'mouseout', state.videoCaption.onMouseLeave
|
||||
);
|
||||
expect($('.subtitles')).toHandleWith(
|
||||
'mousemove', videoCaption.onMovement
|
||||
'mousemove', state.videoCaption.onMovement
|
||||
);
|
||||
expect($('.subtitles')).toHandleWith(
|
||||
'mousewheel', videoCaption.onMovement
|
||||
'mousewheel', state.videoCaption.onMovement
|
||||
);
|
||||
expect($('.subtitles')).toHandleWith(
|
||||
'DOMMouseScroll', videoCaption.onMovement
|
||||
'DOMMouseScroll', state.videoCaption.onMovement
|
||||
);
|
||||
});
|
||||
|
||||
it('bind the scroll', function () {
|
||||
expect($('.subtitles'))
|
||||
.toHandleWith('scroll', videoCaption.autoShowCaptions);
|
||||
.toHandleWith('scroll', state.videoCaption.autoShowCaptions);
|
||||
expect($('.subtitles'))
|
||||
.toHandleWith('scroll', videoControl.showControls);
|
||||
});
|
||||
@@ -114,7 +113,11 @@
|
||||
|
||||
describe('when on a non touch-based device', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
videoControl = state.videoControl;
|
||||
|
||||
$.fn.scrollTo.reset();
|
||||
});
|
||||
|
||||
it('render the caption', function () {
|
||||
@@ -145,38 +148,43 @@
|
||||
function (index, link) {
|
||||
|
||||
expect($(link)).toHandleWith(
|
||||
'mouseover', videoCaption.captionMouseOverOut
|
||||
'mouseover', state.videoCaption.captionMouseOverOut
|
||||
);
|
||||
expect($(link)).toHandleWith(
|
||||
'mouseout', videoCaption.captionMouseOverOut
|
||||
'mouseout', state.videoCaption.captionMouseOverOut
|
||||
);
|
||||
expect($(link)).toHandleWith(
|
||||
'mousedown', videoCaption.captionMouseDown
|
||||
'mousedown', state.videoCaption.captionMouseDown
|
||||
);
|
||||
expect($(link)).toHandleWith(
|
||||
'click', videoCaption.captionClick
|
||||
'click', state.videoCaption.captionClick
|
||||
);
|
||||
expect($(link)).toHandleWith(
|
||||
'focus', videoCaption.captionFocus
|
||||
'focus', state.videoCaption.captionFocus
|
||||
);
|
||||
expect($(link)).toHandleWith(
|
||||
'blur', videoCaption.captionBlur
|
||||
'blur', state.videoCaption.captionBlur
|
||||
);
|
||||
expect($(link)).toHandleWith(
|
||||
'keydown', videoCaption.captionKeyDown
|
||||
'keydown', state.videoCaption.captionKeyDown
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('set rendered to true', function () {
|
||||
expect(videoCaption.rendered).toBeTruthy();
|
||||
expect(state.videoCaption.rendered).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when on a touch-based device', function () {
|
||||
beforeEach(function () {
|
||||
window.onTouchBasedDevice.andReturn(['iPad']);
|
||||
initialize();
|
||||
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
videoControl = state.videoControl;
|
||||
|
||||
$.fn.scrollTo.reset();
|
||||
});
|
||||
|
||||
it('show explaination message', function () {
|
||||
@@ -187,7 +195,7 @@
|
||||
});
|
||||
|
||||
it('does not set rendered to true', function () {
|
||||
expect(videoCaption.rendered).toBeFalsy();
|
||||
expect(state.videoCaption.rendered).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -199,11 +207,10 @@
|
||||
$('#example').find('#video_id').data('sub', '');
|
||||
|
||||
state = new Video('#example');
|
||||
videoCaption = state.videoCaption;
|
||||
});
|
||||
|
||||
it('captions panel is not shown', function () {
|
||||
expect(videoCaption.hideSubtitlesEl).toBeHidden();
|
||||
expect(state.videoCaption.hideSubtitlesEl).toBeHidden();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -221,20 +228,20 @@
|
||||
});
|
||||
|
||||
it('does not set freezing timeout', function () {
|
||||
expect(videoCaption.frozen).toBeFalsy();
|
||||
expect(state.videoCaption.frozen).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when cursor is in the caption box', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(videoCaption, 'onMouseLeave');
|
||||
spyOn(state.videoCaption, 'onMouseLeave');
|
||||
$('.subtitles').trigger(jQuery.Event('mouseenter'));
|
||||
jasmine.Clock.tick(state.config.captionsFreezeTime);
|
||||
});
|
||||
|
||||
it('set the freezing timeout', function () {
|
||||
expect(videoCaption.frozen).not.toBeFalsy();
|
||||
expect(videoCaption.onMouseLeave).toHaveBeenCalled();
|
||||
expect(state.videoCaption.frozen).not.toBeFalsy();
|
||||
expect(state.videoCaption.onMouseLeave).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('when the cursor is moving', function () {
|
||||
@@ -263,7 +270,7 @@
|
||||
function () {
|
||||
|
||||
beforeEach(function () {
|
||||
videoCaption.frozen = 100;
|
||||
state.videoCaption.frozen = 100;
|
||||
$.fn.scrollTo.reset();
|
||||
});
|
||||
|
||||
@@ -277,13 +284,13 @@
|
||||
});
|
||||
|
||||
it('unfreeze the caption', function () {
|
||||
expect(videoCaption.frozen).toBeNull();
|
||||
expect(state.videoCaption.frozen).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the player is playing', function () {
|
||||
beforeEach(function () {
|
||||
videoCaption.playing = true;
|
||||
state.videoCaption.playing = true;
|
||||
$('.subtitles li[data-index]:first')
|
||||
.addClass('current');
|
||||
$('.subtitles').trigger(jQuery.Event('mouseout'));
|
||||
@@ -296,7 +303,7 @@
|
||||
|
||||
describe('when the player is not playing', function () {
|
||||
beforeEach(function () {
|
||||
videoCaption.playing = false;
|
||||
state.videoCaption.playing = false;
|
||||
$('.subtitles').trigger(jQuery.Event('mouseout'));
|
||||
});
|
||||
|
||||
@@ -309,12 +316,12 @@
|
||||
|
||||
describe('search', function () {
|
||||
it('return a correct caption index', function () {
|
||||
expect(videoCaption.search(0)).toEqual(-1);
|
||||
expect(videoCaption.search(3120)).toEqual(1);
|
||||
expect(videoCaption.search(6270)).toEqual(2);
|
||||
expect(videoCaption.search(8490)).toEqual(2);
|
||||
expect(videoCaption.search(21620)).toEqual(4);
|
||||
expect(videoCaption.search(24920)).toEqual(5);
|
||||
expect(state.videoCaption.search(0)).toEqual(-1);
|
||||
expect(state.videoCaption.search(3120)).toEqual(1);
|
||||
expect(state.videoCaption.search(6270)).toEqual(2);
|
||||
expect(state.videoCaption.search(8490)).toEqual(2);
|
||||
expect(state.videoCaption.search(21620)).toEqual(4);
|
||||
expect(state.videoCaption.search(24920)).toEqual(5);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -322,8 +329,14 @@
|
||||
describe('when the caption was not rendered', function () {
|
||||
beforeEach(function () {
|
||||
window.onTouchBasedDevice.andReturn(['iPad']);
|
||||
initialize();
|
||||
videoCaption.play();
|
||||
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
videoControl = state.videoControl;
|
||||
|
||||
$.fn.scrollTo.reset();
|
||||
|
||||
state.videoCaption.play();
|
||||
});
|
||||
|
||||
it('render the caption', function () {
|
||||
@@ -352,78 +365,78 @@
|
||||
function (index, link) {
|
||||
|
||||
expect($(link)).toHandleWith(
|
||||
'mouseover', videoCaption.captionMouseOverOut
|
||||
'mouseover', state.videoCaption.captionMouseOverOut
|
||||
);
|
||||
expect($(link)).toHandleWith(
|
||||
'mouseout', videoCaption.captionMouseOverOut
|
||||
'mouseout', state.videoCaption.captionMouseOverOut
|
||||
);
|
||||
expect($(link)).toHandleWith(
|
||||
'mousedown', videoCaption.captionMouseDown
|
||||
'mousedown', state.videoCaption.captionMouseDown
|
||||
);
|
||||
expect($(link)).toHandleWith(
|
||||
'click', videoCaption.captionClick
|
||||
'click', state.videoCaption.captionClick
|
||||
);
|
||||
expect($(link)).toHandleWith(
|
||||
'focus', videoCaption.captionFocus
|
||||
'focus', state.videoCaption.captionFocus
|
||||
);
|
||||
expect($(link)).toHandleWith(
|
||||
'blur', videoCaption.captionBlur
|
||||
'blur', state.videoCaption.captionBlur
|
||||
);
|
||||
expect($(link)).toHandleWith(
|
||||
'keydown', videoCaption.captionKeyDown
|
||||
'keydown', state.videoCaption.captionKeyDown
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('set rendered to true', function () {
|
||||
expect(videoCaption.rendered).toBeTruthy();
|
||||
expect(state.videoCaption.rendered).toBeTruthy();
|
||||
});
|
||||
|
||||
it('set playing to true', function () {
|
||||
expect(videoCaption.playing).toBeTruthy();
|
||||
expect(state.videoCaption.playing).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('pause', function () {
|
||||
beforeEach(function () {
|
||||
videoCaption.playing = true;
|
||||
videoCaption.pause();
|
||||
state.videoCaption.playing = true;
|
||||
state.videoCaption.pause();
|
||||
});
|
||||
|
||||
it('set playing to false', function () {
|
||||
expect(videoCaption.playing).toBeFalsy();
|
||||
expect(state.videoCaption.playing).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('updatePlayTime', function () {
|
||||
describe('when the video speed is 1.0x', function () {
|
||||
beforeEach(function () {
|
||||
videoSpeedControl.currentSpeed = '1.0';
|
||||
videoCaption.updatePlayTime(25.000);
|
||||
state.videoSpeedControl.currentSpeed = '1.0';
|
||||
state.videoCaption.updatePlayTime(25.000);
|
||||
});
|
||||
|
||||
it('search the caption based on time', function () {
|
||||
expect(videoCaption.currentIndex).toEqual(5);
|
||||
expect(state.videoCaption.currentIndex).toEqual(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the video speed is not 1.0x', function () {
|
||||
beforeEach(function () {
|
||||
videoSpeedControl.currentSpeed = '0.75';
|
||||
videoCaption.updatePlayTime(25.000);
|
||||
state.videoSpeedControl.currentSpeed = '0.75';
|
||||
state.videoCaption.updatePlayTime(25.000);
|
||||
});
|
||||
|
||||
it('search the caption based on 1.0x speed', function () {
|
||||
expect(videoCaption.currentIndex).toEqual(5);
|
||||
expect(state.videoCaption.currentIndex).toEqual(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the index is not the same', function () {
|
||||
beforeEach(function () {
|
||||
videoCaption.currentIndex = 1;
|
||||
state.videoCaption.currentIndex = 1;
|
||||
$('.subtitles li[data-index=5]').addClass('current');
|
||||
videoCaption.updatePlayTime(25.000);
|
||||
state.videoCaption.updatePlayTime(25.000);
|
||||
});
|
||||
|
||||
it('deactivate the previous caption', function () {
|
||||
@@ -437,7 +450,7 @@
|
||||
});
|
||||
|
||||
it('save new index', function () {
|
||||
expect(videoCaption.currentIndex).toEqual(5);
|
||||
expect(state.videoCaption.currentIndex).toEqual(5);
|
||||
});
|
||||
|
||||
// Disabled 11/25/13 due to flakiness in master
|
||||
@@ -448,9 +461,9 @@
|
||||
|
||||
describe('when the index is the same', function () {
|
||||
beforeEach(function () {
|
||||
videoCaption.currentIndex = 1;
|
||||
state.videoCaption.currentIndex = 1;
|
||||
$('.subtitles li[data-index=3]').addClass('current');
|
||||
videoCaption.updatePlayTime(15.000);
|
||||
state.videoCaption.updatePlayTime(15.000);
|
||||
});
|
||||
|
||||
it('does not change current subtitle', function () {
|
||||
@@ -462,9 +475,14 @@
|
||||
|
||||
describe('resize', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
videoControl = state.videoControl;
|
||||
|
||||
$.fn.scrollTo.reset();
|
||||
|
||||
$('.subtitles li[data-index=1]').addClass('current');
|
||||
videoCaption.resize();
|
||||
state.videoCaption.resize();
|
||||
});
|
||||
|
||||
describe('set the height of caption container', function () {
|
||||
@@ -484,7 +502,7 @@
|
||||
controlHeight, shouldBeHeight;
|
||||
|
||||
state.captionsHidden = true;
|
||||
videoCaption.setSubtitlesHeight();
|
||||
state.videoCaption.setSubtitlesHeight();
|
||||
|
||||
realHeight = parseInt(
|
||||
$('.subtitles').css('maxHeight'), 10
|
||||
@@ -510,9 +528,9 @@
|
||||
$('.subtitles .spacing:last').css('height'), 10
|
||||
));
|
||||
|
||||
expect(firstSpacing - videoCaption.topSpacingHeight())
|
||||
expect(firstSpacing - state.videoCaption.topSpacingHeight())
|
||||
.toBeLessThan(1);
|
||||
expect(lastSpacing - videoCaption.bottomSpacingHeight())
|
||||
expect(lastSpacing - state.videoCaption.bottomSpacingHeight())
|
||||
.toBeLessThan(1);
|
||||
});
|
||||
|
||||
@@ -524,14 +542,18 @@
|
||||
// Disabled 11/25/13 due to flakiness in master
|
||||
xdescribe('scrollCaption', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
videoControl = state.videoControl;
|
||||
|
||||
$.fn.scrollTo.reset();
|
||||
});
|
||||
|
||||
describe('when frozen', function () {
|
||||
beforeEach(function () {
|
||||
videoCaption.frozen = true;
|
||||
state.videoCaption.frozen = true;
|
||||
$('.subtitles li[data-index=1]').addClass('current');
|
||||
videoCaption.scrollCaption();
|
||||
state.videoCaption.scrollCaption();
|
||||
});
|
||||
|
||||
it('does not scroll the caption', function () {
|
||||
@@ -541,12 +563,12 @@
|
||||
|
||||
describe('when not frozen', function () {
|
||||
beforeEach(function () {
|
||||
videoCaption.frozen = false;
|
||||
state.videoCaption.frozen = false;
|
||||
});
|
||||
|
||||
describe('when there is no current caption', function () {
|
||||
beforeEach(function () {
|
||||
videoCaption.scrollCaption();
|
||||
state.videoCaption.scrollCaption();
|
||||
});
|
||||
|
||||
it('does not scroll the caption', function () {
|
||||
@@ -557,7 +579,7 @@
|
||||
describe('when there is a current caption', function () {
|
||||
beforeEach(function () {
|
||||
$('.subtitles li[data-index=1]').addClass('current');
|
||||
videoCaption.scrollCaption();
|
||||
state.videoCaption.scrollCaption();
|
||||
});
|
||||
|
||||
it('scroll to current caption', function () {
|
||||
@@ -571,24 +593,29 @@
|
||||
xdescribe('seekPlayer', function () {
|
||||
describe('when the video speed is 1.0x', function () {
|
||||
beforeEach(function () {
|
||||
videoSpeedControl.currentSpeed = '1.0';
|
||||
state.videoSpeedControl.currentSpeed = '1.0';
|
||||
$('.subtitles li[data-start="14910"]').trigger('click');
|
||||
});
|
||||
|
||||
it('trigger seek event with the correct time', function () {
|
||||
expect(videoPlayer.currentTime).toEqual(14.91);
|
||||
expect(state.videoPlayer.currentTime).toEqual(14.91);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the video speed is not 1.0x', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
videoSpeedControl.currentSpeed = '0.75';
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
videoControl = state.videoControl;
|
||||
|
||||
$.fn.scrollTo.reset();
|
||||
|
||||
state.videoSpeedControl.currentSpeed = '0.75';
|
||||
$('.subtitles li[data-start="14910"]').trigger('click');
|
||||
});
|
||||
|
||||
it('trigger seek event with the correct time', function () {
|
||||
expect(videoPlayer.currentTime).toEqual(14.91);
|
||||
expect(state.videoPlayer.currentTime).toEqual(14.91);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -596,36 +623,46 @@
|
||||
function () {
|
||||
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
videoSpeedControl.currentSpeed = '0.75';
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
videoControl = state.videoControl;
|
||||
|
||||
$.fn.scrollTo.reset();
|
||||
|
||||
state.videoSpeedControl.currentSpeed = '0.75';
|
||||
state.currentPlayerMode = 'flash';
|
||||
$('.subtitles li[data-start="14910"]').trigger('click');
|
||||
});
|
||||
|
||||
it('trigger seek event with the correct time', function () {
|
||||
expect(videoPlayer.currentTime).toEqual(15);
|
||||
expect(state.videoPlayer.currentTime).toEqual(15);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggle', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
spyOn(videoPlayer, 'log');
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
videoControl = state.videoControl;
|
||||
|
||||
$.fn.scrollTo.reset();
|
||||
|
||||
spyOn(state.videoPlayer, 'log');
|
||||
$('.subtitles li[data-index=1]').addClass('current');
|
||||
});
|
||||
|
||||
describe('when the caption is visible', function () {
|
||||
beforeEach(function () {
|
||||
state.el.removeClass('closed');
|
||||
videoCaption.toggle(jQuery.Event('click'));
|
||||
state.videoCaption.toggle(jQuery.Event('click'));
|
||||
});
|
||||
|
||||
it('log the hide_transcript event', function () {
|
||||
expect(videoPlayer.log).toHaveBeenCalledWith(
|
||||
expect(state.videoPlayer.log).toHaveBeenCalledWith(
|
||||
'hide_transcript',
|
||||
{
|
||||
currentTime: videoPlayer.currentTime
|
||||
currentTime: state.videoPlayer.currentTime
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -643,16 +680,16 @@
|
||||
describe('when the caption is hidden', function () {
|
||||
beforeEach(function () {
|
||||
state.el.addClass('closed');
|
||||
videoCaption.toggle(jQuery.Event('click'));
|
||||
state.videoCaption.toggle(jQuery.Event('click'));
|
||||
|
||||
jasmine.Clock.useMock();
|
||||
});
|
||||
|
||||
it('log the show_transcript event', function () {
|
||||
expect(videoPlayer.log).toHaveBeenCalledWith(
|
||||
expect(state.videoPlayer.log).toHaveBeenCalledWith(
|
||||
'show_transcript',
|
||||
{
|
||||
currentTime: videoPlayer.currentTime
|
||||
currentTime: state.videoPlayer.currentTime
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -685,12 +722,16 @@
|
||||
|
||||
describe('caption accessibility', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
videoControl = state.videoControl;
|
||||
|
||||
$.fn.scrollTo.reset();
|
||||
});
|
||||
|
||||
describe('when getting focus through TAB key', function () {
|
||||
beforeEach(function () {
|
||||
videoCaption.isMouseFocus = false;
|
||||
state.videoCaption.isMouseFocus = false;
|
||||
$('.subtitles li[data-index=0]').trigger(
|
||||
jQuery.Event('focus')
|
||||
);
|
||||
@@ -702,7 +743,7 @@
|
||||
});
|
||||
|
||||
it('has automatic scrolling disabled', function () {
|
||||
expect(videoCaption.autoScrolling).toBe(false);
|
||||
expect(state.videoCaption.autoScrolling).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -719,7 +760,7 @@
|
||||
});
|
||||
|
||||
it('has automatic scrolling enabled', function () {
|
||||
expect(videoCaption.autoScrolling).toBe(true);
|
||||
expect(state.videoCaption.autoScrolling).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -729,7 +770,7 @@
|
||||
function () {
|
||||
|
||||
beforeEach(function () {
|
||||
videoCaption.isMouseFocus = false;
|
||||
state.videoCaption.isMouseFocus = false;
|
||||
$('.subtitles li[data-index=0]')
|
||||
.trigger(jQuery.Event('focus'));
|
||||
$('.subtitles li[data-index=0]')
|
||||
@@ -742,7 +783,7 @@
|
||||
});
|
||||
|
||||
it('has automatic scrolling enabled', function () {
|
||||
expect(videoCaption.autoScrolling).toBe(true);
|
||||
expect(state.videoCaption.autoScrolling).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -757,12 +798,12 @@
|
||||
subDataLiIdx__0 = $('.subtitles li[data-index=0]');
|
||||
subDataLiIdx__1 = $('.subtitles li[data-index=1]');
|
||||
|
||||
videoCaption.isMouseFocus = false;
|
||||
state.videoCaption.isMouseFocus = false;
|
||||
|
||||
subDataLiIdx__0.trigger(jQuery.Event('focus'));
|
||||
subDataLiIdx__0.trigger(jQuery.Event('blur'));
|
||||
|
||||
videoCaption.isMouseFocus = true;
|
||||
state.videoCaption.isMouseFocus = true;
|
||||
|
||||
subDataLiIdx__1.trigger(jQuery.Event('mousedown'));
|
||||
});
|
||||
@@ -776,7 +817,7 @@
|
||||
});
|
||||
|
||||
it('has automatic scrolling enabled', function () {
|
||||
expect(videoCaption.autoScrolling).toBe(true);
|
||||
expect(state.videoCaption.autoScrolling).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,292 +1,310 @@
|
||||
(function() {
|
||||
describe('VideoControl', function() {
|
||||
var state, videoControl, oldOTBD;
|
||||
(function (undefined) {
|
||||
describe('VideoControl', function () {
|
||||
var state, oldOTBD;
|
||||
|
||||
function initialize(fixture) {
|
||||
if (fixture) {
|
||||
loadFixtures(fixture);
|
||||
} else {
|
||||
loadFixtures('video_all.html');
|
||||
}
|
||||
state = new Video('#example');
|
||||
videoControl = state.videoControl;
|
||||
}
|
||||
beforeEach(function () {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine
|
||||
.createSpy('onTouchBasedDevice').andReturn(null);
|
||||
});
|
||||
|
||||
function initializeYouTube() {
|
||||
initialize('video.html');
|
||||
}
|
||||
afterEach(function () {
|
||||
$('source').remove();
|
||||
window.onTouchBasedDevice = oldOTBD;
|
||||
});
|
||||
|
||||
beforeEach(function(){
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn(null);
|
||||
describe('constructor', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
});
|
||||
|
||||
it('render the video controls', function () {
|
||||
expect($('.video-controls')).toContain(
|
||||
[
|
||||
'.slider',
|
||||
'ul.vcr',
|
||||
'a.play',
|
||||
'.vidtime',
|
||||
'.add-fullscreen'
|
||||
].join(',')
|
||||
);
|
||||
|
||||
expect($('.video-controls').find('.vidtime'))
|
||||
.toHaveText('0:00 / 0:00');
|
||||
});
|
||||
|
||||
it('add ARIA attributes to time control', function () {
|
||||
var timeControl = $('div.slider>a');
|
||||
|
||||
expect(timeControl).toHaveAttrs({
|
||||
'role': 'slider',
|
||||
'title': 'video position',
|
||||
'aria-disabled': 'false'
|
||||
});
|
||||
|
||||
expect(timeControl).toHaveAttr('aria-valuetext');
|
||||
});
|
||||
|
||||
it('add ARIA attributes to play control', function () {
|
||||
var playControl = $('ul.vcr a');
|
||||
|
||||
expect(playControl).toHaveAttrs({
|
||||
'role': 'button',
|
||||
'title': 'Play',
|
||||
'aria-disabled': 'false'
|
||||
});
|
||||
});
|
||||
|
||||
it('add ARIA attributes to fullscreen control', function () {
|
||||
var fullScreenControl = $('a.add-fullscreen');
|
||||
|
||||
expect(fullScreenControl).toHaveAttrs({
|
||||
'role': 'button',
|
||||
'title': 'Fill browser',
|
||||
'aria-disabled': 'false'
|
||||
});
|
||||
});
|
||||
|
||||
it('bind the playback button', function () {
|
||||
expect($('.video_control')).toHandleWith(
|
||||
'click',
|
||||
state.videoControl.togglePlayback
|
||||
);
|
||||
});
|
||||
|
||||
describe('when on a non-touch based device', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
});
|
||||
|
||||
it('add the play class to video control', function () {
|
||||
expect($('.video_control')).toHaveClass('play');
|
||||
expect($('.video_control')).toHaveAttr(
|
||||
'title', 'Play'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when on a touch based device', function () {
|
||||
beforeEach(function () {
|
||||
window.onTouchBasedDevice.andReturn(['iPad']);
|
||||
state = jasmine.initializePlayer();
|
||||
});
|
||||
|
||||
it(
|
||||
'does not add the play class to video control',
|
||||
function ()
|
||||
{
|
||||
expect($('.video_control')).toHaveClass('play');
|
||||
expect($('.video_control')).toHaveAttr(
|
||||
'title', 'Play'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('play', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
state.videoControl.play();
|
||||
});
|
||||
|
||||
it('switch playback button to play state', function () {
|
||||
expect($('.video_control')).not.toHaveClass('play');
|
||||
expect($('.video_control')).toHaveClass('pause');
|
||||
expect($('.video_control')).toHaveAttr('title', 'Pause');
|
||||
});
|
||||
});
|
||||
|
||||
describe('pause', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
state.videoControl.pause();
|
||||
});
|
||||
|
||||
it('switch playback button to pause state', function () {
|
||||
expect($('.video_control')).not.toHaveClass('pause');
|
||||
expect($('.video_control')).toHaveClass('play');
|
||||
expect($('.video_control')).toHaveAttr('title', 'Play');
|
||||
});
|
||||
});
|
||||
|
||||
describe('togglePlayback', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
});
|
||||
|
||||
describe(
|
||||
'when the control does not have play or pause class',
|
||||
function ()
|
||||
{
|
||||
beforeEach(function () {
|
||||
$('.video_control').removeClass('play')
|
||||
.removeClass('pause');
|
||||
});
|
||||
|
||||
describe('when the video is playing', function () {
|
||||
beforeEach(function () {
|
||||
$('.video_control').addClass('play');
|
||||
spyOnEvent(state.videoControl, 'pause');
|
||||
state.videoControl.togglePlayback(jQuery.Event('click'));
|
||||
});
|
||||
|
||||
it('does not trigger the pause event', function () {
|
||||
expect('pause').not
|
||||
.toHaveBeenTriggeredOn(state.videoControl);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the video is paused', function () {
|
||||
beforeEach(function () {
|
||||
$('.video_control').addClass('pause');
|
||||
spyOnEvent(state.videoControl, 'play');
|
||||
state.videoControl.togglePlayback(jQuery.Event('click'));
|
||||
});
|
||||
|
||||
it('does not trigger the play event', function () {
|
||||
expect('play').not
|
||||
.toHaveBeenTriggeredOn(state.videoControl);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Play placeholder', function () {
|
||||
var cases = [
|
||||
{
|
||||
name: 'PC',
|
||||
isShown: false,
|
||||
isTouch: null
|
||||
}, {
|
||||
name: 'iPad',
|
||||
isShown: true,
|
||||
isTouch: ['iPad']
|
||||
}, {
|
||||
name: 'Android',
|
||||
isShown: true,
|
||||
isTouch: ['Android']
|
||||
}, {
|
||||
name: 'iPhone',
|
||||
isShown: false,
|
||||
isTouch: ['iPhone']
|
||||
}
|
||||
];
|
||||
|
||||
beforeEach(function () {
|
||||
jasmine.stubRequests();
|
||||
|
||||
spyOn(window.YT, 'Player').andCallThrough();
|
||||
});
|
||||
|
||||
it ('works correctly on calling proper methods', function () {
|
||||
var btnPlay;
|
||||
|
||||
state = jasmine.initializePlayer();
|
||||
btnPlay = state.el.find('.btn-play');
|
||||
|
||||
state.videoControl.showPlayPlaceholder();
|
||||
|
||||
expect(btnPlay).not.toHaveClass('is-hidden');
|
||||
expect(btnPlay).toHaveAttrs({
|
||||
'aria-hidden': 'false',
|
||||
'tabindex': 0
|
||||
});
|
||||
|
||||
state.videoControl.hidePlayPlaceholder();
|
||||
|
||||
expect(btnPlay).toHaveClass('is-hidden');
|
||||
expect(btnPlay).toHaveAttrs({
|
||||
'aria-hidden': 'true',
|
||||
'tabindex': -1
|
||||
});
|
||||
});
|
||||
|
||||
$.each(cases, function (index, data) {
|
||||
var message = [
|
||||
(data.isShown) ? 'is' : 'is not',
|
||||
' shown on',
|
||||
data.name
|
||||
].join('');
|
||||
|
||||
it(message, function () {
|
||||
var btnPlay;
|
||||
|
||||
window.onTouchBasedDevice.andReturn(data.isTouch);
|
||||
state = jasmine.initializePlayer();
|
||||
btnPlay = state.el.find('.btn-play');
|
||||
|
||||
if (data.isShown) {
|
||||
expect(btnPlay).not.toHaveClass('is-hidden');
|
||||
} else {
|
||||
expect(btnPlay).toHaveClass('is-hidden');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$.each(['iPad', 'Android'], function (index, device) {
|
||||
it(
|
||||
'is shown on paused video on ' + device +
|
||||
' in HTML5 player',
|
||||
function ()
|
||||
{
|
||||
var btnPlay;
|
||||
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
state = jasmine.initializePlayer();
|
||||
btnPlay = state.el.find('.btn-play');
|
||||
|
||||
state.videoControl.play();
|
||||
state.videoControl.pause();
|
||||
|
||||
expect(btnPlay).not.toHaveClass('is-hidden');
|
||||
});
|
||||
|
||||
it(
|
||||
'is hidden on playing video on ' + device +
|
||||
' in HTML5 player',
|
||||
function ()
|
||||
{
|
||||
var btnPlay;
|
||||
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
state = jasmine.initializePlayer();
|
||||
btnPlay = state.el.find('.btn-play');
|
||||
|
||||
state.videoControl.play();
|
||||
|
||||
expect(btnPlay).toHaveClass('is-hidden');
|
||||
});
|
||||
|
||||
it(
|
||||
'is hidden on paused video on ' + device +
|
||||
' in YouTube player',
|
||||
function ()
|
||||
{
|
||||
var btnPlay;
|
||||
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
state = jasmine.initializePlayerYouTube();
|
||||
btnPlay = state.el.find('.btn-play');
|
||||
|
||||
state.videoControl.play();
|
||||
state.videoControl.pause();
|
||||
|
||||
expect(btnPlay).toHaveClass('is-hidden');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('show', function () {
|
||||
var controls;
|
||||
|
||||
state = jasmine.initializePlayer();
|
||||
controls = state.el.find('.video-controls');
|
||||
controls.addClass('is-hidden');
|
||||
|
||||
state.videoControl.show();
|
||||
expect(controls).not.toHaveClass('is-hidden');
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
$('source').remove();
|
||||
window.onTouchBasedDevice = oldOTBD;
|
||||
});
|
||||
|
||||
describe('constructor', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
});
|
||||
|
||||
it('render the video controls', function() {
|
||||
expect($('.video-controls')).toContain(
|
||||
['.slider', 'ul.vcr', 'a.play', '.vidtime', '.add-fullscreen'].join(',')
|
||||
);
|
||||
expect($('.video-controls').find('.vidtime')).toHaveText('0:00 / 0:00');
|
||||
});
|
||||
|
||||
it('add ARIA attributes to time control', function () {
|
||||
var timeControl = $('div.slider>a');
|
||||
expect(timeControl).toHaveAttrs({
|
||||
'role': 'slider',
|
||||
'title': 'video position',
|
||||
'aria-disabled': 'false'
|
||||
});
|
||||
expect(timeControl).toHaveAttr('aria-valuetext');
|
||||
});
|
||||
|
||||
it('add ARIA attributes to play control', function () {
|
||||
var playControl = $('ul.vcr a');
|
||||
expect(playControl).toHaveAttrs({
|
||||
'role': 'button',
|
||||
'title': 'Play',
|
||||
'aria-disabled': 'false'
|
||||
});
|
||||
});
|
||||
|
||||
it('add ARIA attributes to fullscreen control', function () {
|
||||
var fullScreenControl = $('a.add-fullscreen');
|
||||
expect(fullScreenControl).toHaveAttrs({
|
||||
'role': 'button',
|
||||
'title': 'Fill browser',
|
||||
'aria-disabled': 'false'
|
||||
});
|
||||
});
|
||||
|
||||
it('bind the playback button', function() {
|
||||
expect($('.video_control')).toHandleWith('click', videoControl.togglePlayback);
|
||||
});
|
||||
|
||||
describe('when on a non-touch based device', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
});
|
||||
|
||||
it('add the play class to video control', function() {
|
||||
expect($('.video_control')).toHaveClass('play');
|
||||
expect($('.video_control')).toHaveAttr('title', 'Play');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when on a touch based device', function() {
|
||||
beforeEach(function() {
|
||||
window.onTouchBasedDevice.andReturn(['iPad']);
|
||||
initialize();
|
||||
});
|
||||
|
||||
it('does not add the play class to video control', function() {
|
||||
expect($('.video_control')).toHaveClass('play');
|
||||
expect($('.video_control')).toHaveAttr('title', 'Play');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('play', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
videoControl.play();
|
||||
});
|
||||
|
||||
it('switch playback button to play state', function() {
|
||||
expect($('.video_control')).not.toHaveClass('play');
|
||||
expect($('.video_control')).toHaveClass('pause');
|
||||
expect($('.video_control')).toHaveAttr('title', 'Pause');
|
||||
});
|
||||
});
|
||||
|
||||
describe('pause', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
videoControl.pause();
|
||||
});
|
||||
|
||||
it('switch playback button to pause state', function() {
|
||||
expect($('.video_control')).not.toHaveClass('pause');
|
||||
expect($('.video_control')).toHaveClass('play');
|
||||
expect($('.video_control')).toHaveAttr('title', 'Play');
|
||||
});
|
||||
});
|
||||
|
||||
describe('togglePlayback', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
});
|
||||
|
||||
describe('when the control does not have play or pause class', function() {
|
||||
beforeEach(function() {
|
||||
$('.video_control').removeClass('play').removeClass('pause');
|
||||
});
|
||||
|
||||
describe('when the video is playing', function() {
|
||||
beforeEach(function() {
|
||||
$('.video_control').addClass('play');
|
||||
spyOnEvent(videoControl, 'pause');
|
||||
videoControl.togglePlayback(jQuery.Event('click'));
|
||||
});
|
||||
|
||||
it('does not trigger the pause event', function() {
|
||||
expect('pause').not.toHaveBeenTriggeredOn(videoControl);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the video is paused', function() {
|
||||
beforeEach(function() {
|
||||
$('.video_control').addClass('pause');
|
||||
spyOnEvent(videoControl, 'play');
|
||||
videoControl.togglePlayback(jQuery.Event('click'));
|
||||
});
|
||||
|
||||
it('does not trigger the play event', function() {
|
||||
expect('play').not.toHaveBeenTriggeredOn(videoControl);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Play placeholder', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
this.oldYT = window.YT;
|
||||
|
||||
jasmine.stubRequests();
|
||||
window.YT = {
|
||||
Player: function () {
|
||||
return { getDuration: function () { return 60; } };
|
||||
},
|
||||
PlayerState: this.oldYT.PlayerState,
|
||||
ready: function (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
spyOn(window.YT, 'Player').andCallThrough();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
window.YT = this.oldYT;
|
||||
});
|
||||
|
||||
|
||||
it ('works correctly on calling proper methods', function () {
|
||||
initialize();
|
||||
var btnPlay = state.el.find('.btn-play');
|
||||
|
||||
videoControl.showPlayPlaceholder();
|
||||
|
||||
expect(btnPlay).not.toHaveClass('is-hidden');
|
||||
expect(btnPlay).toHaveAttrs({
|
||||
'aria-hidden': 'false',
|
||||
'tabindex': 0
|
||||
});
|
||||
|
||||
videoControl.hidePlayPlaceholder();
|
||||
|
||||
expect(btnPlay).toHaveClass('is-hidden');
|
||||
expect(btnPlay).toHaveAttrs({
|
||||
'aria-hidden': 'true',
|
||||
'tabindex': -1
|
||||
});
|
||||
});
|
||||
|
||||
var cases = [
|
||||
{
|
||||
name: 'PC',
|
||||
isShown: false,
|
||||
isTouch: null
|
||||
},
|
||||
{
|
||||
name: 'iPad',
|
||||
isShown: true,
|
||||
isTouch: ['iPad']
|
||||
},
|
||||
{
|
||||
name: 'Android',
|
||||
isShown: true,
|
||||
isTouch: ['Android']
|
||||
},
|
||||
{
|
||||
name: 'iPhone',
|
||||
isShown: false,
|
||||
isTouch: ['iPhone']
|
||||
}
|
||||
];
|
||||
|
||||
$.each(cases, function(index, data) {
|
||||
var message = [
|
||||
(data.isShown) ? 'is' : 'is not',
|
||||
' shown on',
|
||||
data.name
|
||||
].join('');
|
||||
|
||||
it(message, function () {
|
||||
window.onTouchBasedDevice.andReturn(data.isTouch);
|
||||
initialize();
|
||||
var btnPlay = state.el.find('.btn-play');
|
||||
|
||||
if (data.isShown) {
|
||||
expect(btnPlay).not.toHaveClass('is-hidden');
|
||||
} else {
|
||||
expect(btnPlay).toHaveClass('is-hidden');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$.each(['iPad', 'Android'], function(index, device) {
|
||||
it('is shown on paused video on '+ device +' in HTML5 player', function () {
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
initialize();
|
||||
var btnPlay = state.el.find('.btn-play');
|
||||
|
||||
videoControl.play();
|
||||
videoControl.pause();
|
||||
|
||||
expect(btnPlay).not.toHaveClass('is-hidden');
|
||||
});
|
||||
|
||||
it('is hidden on playing video on '+ device +' in HTML5 player', function () {
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
initialize();
|
||||
var btnPlay = state.el.find('.btn-play');
|
||||
|
||||
videoControl.play();
|
||||
|
||||
expect(btnPlay).toHaveClass('is-hidden');
|
||||
});
|
||||
|
||||
it('is hidden on paused video on '+ device +' in YouTube player', function () {
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
initializeYouTube();
|
||||
var btnPlay = state.el.find('.btn-play');
|
||||
|
||||
videoControl.play();
|
||||
videoControl.pause();
|
||||
|
||||
expect(btnPlay).toHaveClass('is-hidden');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('show', function () {
|
||||
initialize();
|
||||
var controls = state.el.find('.video-controls');
|
||||
controls.addClass('is-hidden');
|
||||
|
||||
videoControl.show();
|
||||
expect(controls).not.toHaveClass('is-hidden');
|
||||
});
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(function () {
|
||||
(function (undefined) {
|
||||
describe('Video FocusGrabber', function () {
|
||||
var state;
|
||||
|
||||
|
||||
@@ -1,58 +1,6 @@
|
||||
(function () {
|
||||
(function (undefined) {
|
||||
describe('VideoPlayer', function () {
|
||||
var state, videoPlayer, player, videoControl, videoCaption,
|
||||
videoProgressSlider, videoSpeedControl, videoVolumeControl,
|
||||
oldOTBD;
|
||||
|
||||
function initialize(fixture, params) {
|
||||
if (_.isString(fixture)) {
|
||||
loadFixtures(fixture);
|
||||
} else {
|
||||
if (_.isObject(fixture)) {
|
||||
params = fixture;
|
||||
}
|
||||
|
||||
loadFixtures('video_all.html');
|
||||
}
|
||||
|
||||
if (_.isObject(params)) {
|
||||
$('#example')
|
||||
.find('#video_id')
|
||||
.data(params);
|
||||
}
|
||||
|
||||
state = new Video('#example');
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
videoPlayer = state.videoPlayer;
|
||||
player = videoPlayer.player;
|
||||
videoControl = state.videoControl;
|
||||
videoCaption = state.videoCaption;
|
||||
videoProgressSlider = state.videoProgressSlider;
|
||||
videoSpeedControl = state.videoSpeedControl;
|
||||
videoVolumeControl = state.videoVolumeControl;
|
||||
|
||||
state.resizer = (function () {
|
||||
var methods = [
|
||||
'align',
|
||||
'alignByWidthOnly',
|
||||
'alignByHeightOnly',
|
||||
'setParams',
|
||||
'setMode'
|
||||
],
|
||||
obj = {};
|
||||
|
||||
$.each(methods, function (index, method) {
|
||||
obj[method] = jasmine.createSpy(method).andReturn(obj);
|
||||
});
|
||||
|
||||
return obj;
|
||||
}());
|
||||
}
|
||||
|
||||
function initializeYouTube() {
|
||||
initialize('video.html');
|
||||
}
|
||||
var state, oldOTBD;
|
||||
|
||||
beforeEach(function () {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
@@ -68,11 +16,13 @@
|
||||
describe('constructor', function () {
|
||||
describe('always', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
});
|
||||
|
||||
it('instanticate current time to zero', function () {
|
||||
expect(videoPlayer.currentTime).toEqual(0);
|
||||
expect(state.videoPlayer.currentTime).toEqual(0);
|
||||
});
|
||||
|
||||
it('set the element', function () {
|
||||
@@ -80,12 +30,12 @@
|
||||
});
|
||||
|
||||
it('create video control', function () {
|
||||
expect(videoControl).toBeDefined();
|
||||
expect(videoControl.el).toHaveClass('video-controls');
|
||||
expect(state.videoControl).toBeDefined();
|
||||
expect(state.videoControl.el).toHaveClass('video-controls');
|
||||
});
|
||||
|
||||
it('create video caption', function () {
|
||||
expect(videoCaption).toBeDefined();
|
||||
expect(state.videoCaption).toBeDefined();
|
||||
expect(state.youtubeId()).toEqual('Z5KLxerq05Y');
|
||||
expect(state.speed).toEqual('1.0');
|
||||
expect(state.config.caption_asset_path)
|
||||
@@ -93,16 +43,16 @@
|
||||
});
|
||||
|
||||
it('create video speed control', function () {
|
||||
expect(videoSpeedControl).toBeDefined();
|
||||
expect(videoSpeedControl.el).toHaveClass('speeds');
|
||||
expect(videoSpeedControl.speeds)
|
||||
expect(state.videoSpeedControl).toBeDefined();
|
||||
expect(state.videoSpeedControl.el).toHaveClass('speeds');
|
||||
expect(state.videoSpeedControl.speeds)
|
||||
.toEqual([ '0.75', '1.0', '1.25', '1.50' ]);
|
||||
expect(state.speed).toEqual('1.0');
|
||||
});
|
||||
|
||||
it('create video progress slider', function () {
|
||||
expect(videoProgressSlider).toBeDefined();
|
||||
expect(videoProgressSlider.el).toHaveClass('slider');
|
||||
expect(state.videoProgressSlider).toBeDefined();
|
||||
expect(state.videoProgressSlider.el).toHaveClass('slider');
|
||||
});
|
||||
|
||||
// All the toHandleWith() expect tests are not necessary for
|
||||
@@ -112,28 +62,20 @@
|
||||
});
|
||||
|
||||
it('create Youtube player', function () {
|
||||
var oldYT = window.YT, events;
|
||||
var events;
|
||||
|
||||
jasmine.stubRequests();
|
||||
|
||||
window.YT = {
|
||||
Player: function () {
|
||||
return { getDuration: function () { return 60; } };
|
||||
},
|
||||
PlayerState: oldYT.PlayerState,
|
||||
ready: function (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
spyOn(window.YT, 'Player').andCallThrough();
|
||||
|
||||
initializeYouTube();
|
||||
state = jasmine.initializePlayerYouTube();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
events = {
|
||||
onReady: videoPlayer.onReady,
|
||||
onStateChange: videoPlayer.onStateChange,
|
||||
onPlaybackQualityChange: videoPlayer
|
||||
onReady: state.videoPlayer.onReady,
|
||||
onStateChange: state.videoPlayer.onStateChange,
|
||||
onPlaybackQualityChange: state.videoPlayer
|
||||
.onPlaybackQualityChange
|
||||
};
|
||||
|
||||
@@ -150,8 +92,6 @@
|
||||
videoId: 'cogebirgzzM',
|
||||
events: events
|
||||
});
|
||||
|
||||
window.YT = oldYT;
|
||||
});
|
||||
|
||||
// We can't test the invocation of HTML5Video because it is not
|
||||
@@ -159,11 +99,14 @@
|
||||
// JS.
|
||||
|
||||
describe('when on a touch based device', function () {
|
||||
$.each(['iPad', 'Android'], function(index, device) {
|
||||
it('create video volume control on' + device, function() {
|
||||
$.each(['iPad', 'Android'], function (index, device) {
|
||||
it('create video volume control on' + device, function () {
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
initialize();
|
||||
expect(videoVolumeControl).toBeUndefined();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
expect(state.videoVolumeControl).toBeUndefined();
|
||||
expect(state.el.find('div.volume')).not.toExist();
|
||||
});
|
||||
});
|
||||
@@ -173,52 +116,58 @@
|
||||
var oldOTBD;
|
||||
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
});
|
||||
|
||||
it('controls are in paused state', function () {
|
||||
expect(videoControl.isPlaying).toBe(false);
|
||||
expect(state.videoControl.isPlaying).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('onReady', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
spyOn(videoPlayer, 'log').andCallThrough();
|
||||
spyOn(videoPlayer, 'play').andCallThrough();
|
||||
videoPlayer.onReady();
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoPlayer, 'log').andCallThrough();
|
||||
spyOn(state.videoPlayer, 'play').andCallThrough();
|
||||
state.videoPlayer.onReady();
|
||||
});
|
||||
|
||||
it('log the load_video event', function () {
|
||||
expect(videoPlayer.log).toHaveBeenCalledWith('load_video');
|
||||
expect(state.videoPlayer.log).toHaveBeenCalledWith('load_video');
|
||||
});
|
||||
|
||||
it('autoplay the first video', function () {
|
||||
expect(videoPlayer.play).not.toHaveBeenCalled();
|
||||
expect(state.videoPlayer.play).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onStateChange', function () {
|
||||
describe('when the video is unstarted', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
spyOn(videoControl, 'pause').andCallThrough();
|
||||
spyOn(videoCaption, 'pause').andCallThrough();
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
videoPlayer.onStateChange({
|
||||
data: YT.PlayerState.PAUSED
|
||||
spyOn(state.videoControl, 'pause').andCallThrough();
|
||||
spyOn(state.videoCaption, 'pause').andCallThrough();
|
||||
|
||||
state.videoPlayer.onStateChange({
|
||||
data: YT.PlayerState.PAUSED
|
||||
});
|
||||
});
|
||||
|
||||
it('pause the video control', function () {
|
||||
expect(videoControl.pause).toHaveBeenCalled();
|
||||
expect(state.videoControl.pause).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('pause the video caption', function () {
|
||||
expect(videoCaption.pause).toHaveBeenCalled();
|
||||
expect(state.videoCaption.pause).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -227,26 +176,28 @@
|
||||
|
||||
beforeEach(function () {
|
||||
// Create the first instance of the player.
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
oldState = state;
|
||||
|
||||
spyOn(oldState.videoPlayer, 'onPause').andCallThrough();
|
||||
|
||||
// Now initialize a second instance.
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
spyOn(videoPlayer, 'log').andCallThrough();
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoPlayer, 'log').andCallThrough();
|
||||
spyOn(window, 'setInterval').andReturn(100);
|
||||
spyOn(videoControl, 'play');
|
||||
spyOn(videoCaption, 'play');
|
||||
spyOn(state.videoControl, 'play');
|
||||
spyOn(state.videoCaption, 'play');
|
||||
|
||||
videoPlayer.onStateChange({
|
||||
state.videoPlayer.onStateChange({
|
||||
data: YT.PlayerState.PLAYING
|
||||
});
|
||||
});
|
||||
|
||||
it('log the play_video event', function () {
|
||||
expect(videoPlayer.log).toHaveBeenCalledWith(
|
||||
expect(state.videoPlayer.log).toHaveBeenCalledWith(
|
||||
'play_video', { currentTime: 0 }
|
||||
);
|
||||
});
|
||||
@@ -257,17 +208,17 @@
|
||||
|
||||
it('set update interval', function () {
|
||||
expect(window.setInterval).toHaveBeenCalledWith(
|
||||
videoPlayer.update, 200
|
||||
state.videoPlayer.update, 200
|
||||
);
|
||||
expect(videoPlayer.updateInterval).toEqual(100);
|
||||
expect(state.videoPlayer.updateInterval).toEqual(100);
|
||||
});
|
||||
|
||||
it('play the video control', function () {
|
||||
expect(videoControl.play).toHaveBeenCalled();
|
||||
expect(state.videoControl.play).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('play the video caption', function () {
|
||||
expect(videoCaption.play).toHaveBeenCalled();
|
||||
expect(state.videoCaption.play).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -275,90 +226,96 @@
|
||||
var currentUpdateIntrval;
|
||||
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
spyOn(videoPlayer, 'log').andCallThrough();
|
||||
spyOn(videoControl, 'pause').andCallThrough();
|
||||
spyOn(videoCaption, 'pause').andCallThrough();
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
videoPlayer.onStateChange({
|
||||
spyOn(state.videoPlayer, 'log').andCallThrough();
|
||||
spyOn(state.videoControl, 'pause').andCallThrough();
|
||||
spyOn(state.videoCaption, 'pause').andCallThrough();
|
||||
|
||||
state.videoPlayer.onStateChange({
|
||||
data: YT.PlayerState.PLAYING
|
||||
});
|
||||
|
||||
currentUpdateIntrval = videoPlayer.updateInterval;
|
||||
currentUpdateIntrval = state.videoPlayer.updateInterval;
|
||||
|
||||
videoPlayer.onStateChange({
|
||||
state.videoPlayer.onStateChange({
|
||||
data: YT.PlayerState.PAUSED
|
||||
});
|
||||
});
|
||||
|
||||
it('log the pause_video event', function () {
|
||||
expect(videoPlayer.log).toHaveBeenCalledWith(
|
||||
expect(state.videoPlayer.log).toHaveBeenCalledWith(
|
||||
'pause_video', { currentTime: 0 }
|
||||
);
|
||||
});
|
||||
|
||||
it('clear update interval', function () {
|
||||
expect(videoPlayer.updateInterval).toBeUndefined();
|
||||
expect(state.videoPlayer.updateInterval).toBeUndefined();
|
||||
});
|
||||
|
||||
it('pause the video control', function () {
|
||||
expect(videoControl.pause).toHaveBeenCalled();
|
||||
expect(state.videoControl.pause).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('pause the video caption', function () {
|
||||
expect(videoCaption.pause).toHaveBeenCalled();
|
||||
expect(state.videoCaption.pause).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the video is ended', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
spyOn(videoControl, 'pause').andCallThrough();
|
||||
spyOn(videoCaption, 'pause').andCallThrough();
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
videoPlayer.onStateChange({
|
||||
spyOn(state.videoControl, 'pause').andCallThrough();
|
||||
spyOn(state.videoCaption, 'pause').andCallThrough();
|
||||
|
||||
state.videoPlayer.onStateChange({
|
||||
data: YT.PlayerState.ENDED
|
||||
});
|
||||
});
|
||||
|
||||
it('pause the video control', function () {
|
||||
expect(videoControl.pause).toHaveBeenCalled();
|
||||
expect(state.videoControl.pause).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('pause the video caption', function () {
|
||||
expect(videoCaption.pause).toHaveBeenCalled();
|
||||
expect(state.videoCaption.pause).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSeek', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
runs(function () {
|
||||
state.videoPlayer.play();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
duration = videoPlayer.duration();
|
||||
duration = state.videoPlayer.duration();
|
||||
|
||||
return duration > 0 && videoPlayer.isPlaying();
|
||||
return duration > 0 && state.videoPlayer.isPlaying();
|
||||
}, 'video begins playing', WAIT_TIMEOUT);
|
||||
});
|
||||
|
||||
it('Slider event causes log update', function () {
|
||||
|
||||
runs(function () {
|
||||
var currentTime = videoPlayer.currentTime;
|
||||
var currentTime = state.videoPlayer.currentTime;
|
||||
|
||||
spyOn(videoPlayer, 'log');
|
||||
videoProgressSlider.onSlide(
|
||||
spyOn(state.videoPlayer, 'log');
|
||||
state.videoProgressSlider.onSlide(
|
||||
jQuery.Event('slide'), { value: 2 }
|
||||
);
|
||||
|
||||
expect(videoPlayer.log).toHaveBeenCalledWith(
|
||||
expect(state.videoPlayer.log).toHaveBeenCalledWith(
|
||||
'seek_video',
|
||||
{
|
||||
old_time: currentTime,
|
||||
@@ -371,24 +328,24 @@
|
||||
|
||||
it('seek the player', function () {
|
||||
runs(function () {
|
||||
spyOn(videoPlayer.player, 'seekTo');
|
||||
videoProgressSlider.onSlide(
|
||||
spyOn(state.videoPlayer.player, 'seekTo');
|
||||
state.videoProgressSlider.onSlide(
|
||||
jQuery.Event('slide'), { value: 60 }
|
||||
);
|
||||
|
||||
expect(videoPlayer.player.seekTo)
|
||||
expect(state.videoPlayer.player.seekTo)
|
||||
.toHaveBeenCalledWith(60, true);
|
||||
});
|
||||
});
|
||||
|
||||
it('call updatePlayTime on player', function () {
|
||||
runs(function () {
|
||||
spyOn(videoPlayer, 'updatePlayTime');
|
||||
videoProgressSlider.onSlide(
|
||||
spyOn(state.videoPlayer, 'updatePlayTime');
|
||||
state.videoProgressSlider.onSlide(
|
||||
jQuery.Event('slide'), { value: 60 }
|
||||
);
|
||||
|
||||
expect(videoPlayer.updatePlayTime)
|
||||
expect(state.videoPlayer.updatePlayTime)
|
||||
.toHaveBeenCalledWith(60);
|
||||
});
|
||||
});
|
||||
@@ -399,16 +356,16 @@
|
||||
function ()
|
||||
{
|
||||
runs(function () {
|
||||
videoProgressSlider.onSlide(
|
||||
state.videoProgressSlider.onSlide(
|
||||
jQuery.Event('slide'), { value: 20 }
|
||||
);
|
||||
videoPlayer.pause();
|
||||
videoProgressSlider.onSlide(
|
||||
state.videoPlayer.pause();
|
||||
state.videoProgressSlider.onSlide(
|
||||
jQuery.Event('slide'), { value: 10 }
|
||||
);
|
||||
|
||||
waitsFor(function () {
|
||||
return Math.round(videoPlayer.currentTime) === 10;
|
||||
return Math.round(state.videoPlayer.currentTime) === 10;
|
||||
}, 'currentTime got updated', 10000);
|
||||
});
|
||||
});
|
||||
@@ -416,26 +373,28 @@
|
||||
|
||||
describe('onSpeedChange', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
spyOn(videoPlayer, 'updatePlayTime').andCallThrough();
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoPlayer, 'updatePlayTime').andCallThrough();
|
||||
spyOn(state, 'setSpeed').andCallThrough();
|
||||
spyOn(videoPlayer, 'log').andCallThrough();
|
||||
spyOn(videoPlayer.player, 'setPlaybackRate').andCallThrough();
|
||||
spyOn(state.videoPlayer, 'log').andCallThrough();
|
||||
spyOn(state.videoPlayer.player, 'setPlaybackRate').andCallThrough();
|
||||
});
|
||||
|
||||
describe('always', function () {
|
||||
beforeEach(function () {
|
||||
|
||||
videoPlayer.currentTime = 60;
|
||||
videoPlayer.onSpeedChange('0.75', false);
|
||||
state.videoPlayer.currentTime = 60;
|
||||
state.videoPlayer.onSpeedChange('0.75', false);
|
||||
});
|
||||
|
||||
it('check if speed_change_video is logged', function () {
|
||||
expect(videoPlayer.log).toHaveBeenCalledWith(
|
||||
expect(state.videoPlayer.log).toHaveBeenCalledWith(
|
||||
'speed_change_video',
|
||||
{
|
||||
current_time: videoPlayer.currentTime,
|
||||
current_time: state.videoPlayer.currentTime,
|
||||
old_speed: '1.0',
|
||||
new_speed: '0.75'
|
||||
}
|
||||
@@ -443,7 +402,7 @@
|
||||
});
|
||||
|
||||
it('convert the current time to the new speed', function () {
|
||||
expect(videoPlayer.currentTime).toEqual(60);
|
||||
expect(state.videoPlayer.currentTime).toEqual(60);
|
||||
});
|
||||
|
||||
it('set video speed to the new speed', function () {
|
||||
@@ -453,75 +412,82 @@
|
||||
|
||||
describe('when the video is playing', function () {
|
||||
beforeEach(function () {
|
||||
videoPlayer.currentTime = 60;
|
||||
videoPlayer.play();
|
||||
videoPlayer.onSpeedChange('0.75', false);
|
||||
state.videoPlayer.currentTime = 60;
|
||||
state.videoPlayer.play();
|
||||
state.videoPlayer.onSpeedChange('0.75', false);
|
||||
});
|
||||
|
||||
it('trigger updatePlayTime event', function () {
|
||||
expect(videoPlayer.player.setPlaybackRate)
|
||||
expect(state.videoPlayer.player.setPlaybackRate)
|
||||
.toHaveBeenCalledWith('0.75');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the video is not playing', function () {
|
||||
beforeEach(function () {
|
||||
videoPlayer.onSpeedChange('0.75', false);
|
||||
state.videoPlayer.onSpeedChange('0.75', false);
|
||||
});
|
||||
|
||||
it('trigger updatePlayTime event', function () {
|
||||
expect(videoPlayer.player.setPlaybackRate)
|
||||
expect(state.videoPlayer.player.setPlaybackRate)
|
||||
.toHaveBeenCalledWith('0.75');
|
||||
});
|
||||
|
||||
it('video has a correct speed', function () {
|
||||
spyOn(videoPlayer, 'onSpeedChange');
|
||||
spyOn(state.videoPlayer, 'onSpeedChange');
|
||||
state.speed = '2.0';
|
||||
videoPlayer.onPlay();
|
||||
expect(videoPlayer.onSpeedChange).toHaveBeenCalledWith('2.0');
|
||||
videoPlayer.onPlay();
|
||||
expect(videoPlayer.onSpeedChange.calls.length).toEqual(1);
|
||||
state.videoPlayer.onPlay();
|
||||
expect(state.videoPlayer.onSpeedChange)
|
||||
.toHaveBeenCalledWith('2.0');
|
||||
state.videoPlayer.onPlay();
|
||||
expect(state.videoPlayer.onSpeedChange.calls.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('video has a correct volume', function () {
|
||||
spyOn(videoPlayer.player, 'setVolume');
|
||||
spyOn(state.videoPlayer.player, 'setVolume');
|
||||
state.currentVolume = '0.26';
|
||||
videoPlayer.onPlay();
|
||||
expect(videoPlayer.player.setVolume).toHaveBeenCalledWith('0.26');
|
||||
state.videoPlayer.onPlay();
|
||||
expect(state.videoPlayer.player.setVolume)
|
||||
.toHaveBeenCalledWith('0.26');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('onVolumeChange', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
});
|
||||
|
||||
it('set the volume on player', function () {
|
||||
spyOn(videoPlayer.player, 'setVolume');
|
||||
videoPlayer.onVolumeChange(60);
|
||||
expect(videoPlayer.player.setVolume).toHaveBeenCalledWith(60);
|
||||
spyOn(state.videoPlayer.player, 'setVolume');
|
||||
state.videoPlayer.onVolumeChange(60);
|
||||
expect(state.videoPlayer.player.setVolume).toHaveBeenCalledWith(60);
|
||||
});
|
||||
|
||||
describe('when the video is not playing', function () {
|
||||
beforeEach(function () {
|
||||
videoPlayer.player.setVolume('1');
|
||||
state.videoPlayer.player.setVolume('1');
|
||||
});
|
||||
|
||||
it('video has a correct volume', function () {
|
||||
spyOn(videoPlayer.player, 'setVolume');
|
||||
spyOn(state.videoPlayer.player, 'setVolume');
|
||||
state.currentVolume = '0.26';
|
||||
videoPlayer.onPlay();
|
||||
expect(videoPlayer.player.setVolume).toHaveBeenCalledWith('0.26');
|
||||
state.videoPlayer.onPlay();
|
||||
expect(state.videoPlayer.player.setVolume)
|
||||
.toHaveBeenCalledWith('0.26');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
spyOn(videoPlayer, 'updatePlayTime').andCallThrough();
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoPlayer, 'updatePlayTime').andCallThrough();
|
||||
});
|
||||
|
||||
describe(
|
||||
@@ -529,14 +495,14 @@
|
||||
function ()
|
||||
{
|
||||
beforeEach(function () {
|
||||
videoPlayer.player.getCurrentTime = function () {
|
||||
state.videoPlayer.player.getCurrentTime = function () {
|
||||
return NaN;
|
||||
};
|
||||
videoPlayer.update();
|
||||
state.videoPlayer.update();
|
||||
});
|
||||
|
||||
it('does not trigger updatePlayTime event', function () {
|
||||
expect(videoPlayer.updatePlayTime).not.toHaveBeenCalled();
|
||||
expect(state.videoPlayer.updatePlayTime).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -545,14 +511,14 @@
|
||||
function ()
|
||||
{
|
||||
beforeEach(function () {
|
||||
videoPlayer.player.getCurrentTime = function () {
|
||||
state.videoPlayer.player.getCurrentTime = function () {
|
||||
return 60;
|
||||
};
|
||||
videoPlayer.update();
|
||||
state.videoPlayer.update();
|
||||
});
|
||||
|
||||
it('trigger updatePlayTime event', function () {
|
||||
expect(videoPlayer.updatePlayTime)
|
||||
expect(state.videoPlayer.updatePlayTime)
|
||||
.toHaveBeenCalledWith(60);
|
||||
});
|
||||
});
|
||||
@@ -563,34 +529,44 @@
|
||||
var START_TIME = 1, END_TIME = 2;
|
||||
|
||||
beforeEach(function () {
|
||||
initialize({start: START_TIME, end: END_TIME});
|
||||
state = jasmine.initializePlayer(
|
||||
{
|
||||
start: START_TIME,
|
||||
end: END_TIME
|
||||
}
|
||||
);
|
||||
|
||||
spyOn(videoPlayer, 'update').andCallThrough();
|
||||
spyOn(videoPlayer, 'pause').andCallThrough();
|
||||
spyOn(videoProgressSlider, 'notifyThroughHandleEnd')
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoPlayer, 'update').andCallThrough();
|
||||
spyOn(state.videoPlayer, 'pause').andCallThrough();
|
||||
spyOn(state.videoProgressSlider, 'notifyThroughHandleEnd')
|
||||
.andCallThrough();
|
||||
});
|
||||
|
||||
it('video is paused on first endTime, start & end time are reset', function () {
|
||||
it(
|
||||
'video is paused on first endTime, start & end time are reset',
|
||||
function ()
|
||||
{
|
||||
var duration;
|
||||
|
||||
videoProgressSlider.notifyThroughHandleEnd.reset();
|
||||
videoPlayer.pause.reset();
|
||||
videoPlayer.play();
|
||||
state.videoProgressSlider.notifyThroughHandleEnd.reset();
|
||||
state.videoPlayer.pause.reset();
|
||||
state.videoPlayer.play();
|
||||
|
||||
waitsFor(function () {
|
||||
duration = Math.round(videoPlayer.currentTime);
|
||||
duration = Math.round(state.videoPlayer.currentTime);
|
||||
|
||||
return videoPlayer.pause.calls.length === 1;
|
||||
return state.videoPlayer.pause.calls.length === 1;
|
||||
}, 'pause() has been called', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(videoPlayer.startTime).toBe(0);
|
||||
expect(videoPlayer.endTime).toBe(null);
|
||||
expect(state.videoPlayer.startTime).toBe(0);
|
||||
expect(state.videoPlayer.endTime).toBe(null);
|
||||
|
||||
expect(duration).toBe(END_TIME);
|
||||
|
||||
expect(videoProgressSlider.notifyThroughHandleEnd)
|
||||
expect(state.videoProgressSlider.notifyThroughHandleEnd)
|
||||
.toHaveBeenCalledWith({end: true});
|
||||
});
|
||||
});
|
||||
@@ -598,17 +574,19 @@
|
||||
|
||||
describe('updatePlayTime', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
spyOn(videoCaption, 'updatePlayTime').andCallThrough();
|
||||
spyOn(videoProgressSlider, 'updatePlayTime').andCallThrough();
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoCaption, 'updatePlayTime').andCallThrough();
|
||||
spyOn(state.videoProgressSlider, 'updatePlayTime').andCallThrough();
|
||||
});
|
||||
|
||||
it('update the video playback time', function () {
|
||||
var duration = 0;
|
||||
|
||||
waitsFor(function () {
|
||||
duration = videoPlayer.duration();
|
||||
duration = state.videoPlayer.duration();
|
||||
|
||||
if (duration > 0) {
|
||||
return true;
|
||||
@@ -620,7 +598,7 @@
|
||||
runs(function () {
|
||||
var htmlStr;
|
||||
|
||||
videoPlayer.updatePlayTime(60);
|
||||
state.videoPlayer.updatePlayTime(60);
|
||||
|
||||
htmlStr = $('.vidtime').html();
|
||||
|
||||
@@ -643,13 +621,13 @@
|
||||
|
||||
it('update the playback time on caption', function () {
|
||||
waitsFor(function () {
|
||||
return videoPlayer.duration() > 0;
|
||||
return state.videoPlayer.duration() > 0;
|
||||
}, 'Video is fully loaded.', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
videoPlayer.updatePlayTime(60);
|
||||
state.videoPlayer.updatePlayTime(60);
|
||||
|
||||
expect(videoCaption.updatePlayTime)
|
||||
expect(state.videoCaption.updatePlayTime)
|
||||
.toHaveBeenCalledWith(60);
|
||||
});
|
||||
});
|
||||
@@ -658,15 +636,15 @@
|
||||
var duration = 0;
|
||||
|
||||
waitsFor(function () {
|
||||
duration = videoPlayer.duration();
|
||||
duration = state.videoPlayer.duration();
|
||||
|
||||
return duration > 0;
|
||||
}, 'Video is fully loaded.', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
videoPlayer.updatePlayTime(60);
|
||||
state.videoPlayer.updatePlayTime(60);
|
||||
|
||||
expect(videoProgressSlider.updatePlayTime)
|
||||
expect(state.videoProgressSlider.updatePlayTime)
|
||||
.toHaveBeenCalledWith({
|
||||
time: 60,
|
||||
duration: duration
|
||||
@@ -676,68 +654,93 @@
|
||||
});
|
||||
|
||||
// Disabled 1/13/14 due to flakiness observed in master
|
||||
xdescribe('updatePlayTime when start & end times are defined', function () {
|
||||
xdescribe(
|
||||
'updatePlayTime when start & end times are defined',
|
||||
function ()
|
||||
{
|
||||
var START_TIME = 1,
|
||||
END_TIME = 2;
|
||||
|
||||
beforeEach(function () {
|
||||
initialize({start: START_TIME, end: END_TIME});
|
||||
state = jasmine.initializePlayer(
|
||||
{
|
||||
start: START_TIME,
|
||||
end: END_TIME
|
||||
}
|
||||
);
|
||||
|
||||
spyOn(videoPlayer, 'updatePlayTime').andCallThrough();
|
||||
spyOn(videoPlayer.player, 'seekTo').andCallThrough();
|
||||
spyOn(videoProgressSlider, 'updateStartEndTimeRegion')
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoPlayer, 'updatePlayTime').andCallThrough();
|
||||
spyOn(state.videoPlayer.player, 'seekTo').andCallThrough();
|
||||
spyOn(state.videoProgressSlider, 'updateStartEndTimeRegion')
|
||||
.andCallThrough();
|
||||
});
|
||||
|
||||
it('when duration becomes available, updatePlayTime() is called', function () {
|
||||
it(
|
||||
'when duration becomes available, updatePlayTime() is called',
|
||||
function ()
|
||||
{
|
||||
var duration;
|
||||
|
||||
expect(videoPlayer.initialSeekToStartTime).toBeTruthy();
|
||||
expect(videoPlayer.seekToStartTimeOldSpeed).toBe('void');
|
||||
expect(state.videoPlayer.initialSeekToStartTime).toBeTruthy();
|
||||
expect(state.videoPlayer.seekToStartTimeOldSpeed).toBe('void');
|
||||
|
||||
videoPlayer.play();
|
||||
state.videoPlayer.play();
|
||||
|
||||
waitsFor(function () {
|
||||
duration = videoPlayer.duration();
|
||||
duration = state.videoPlayer.duration();
|
||||
|
||||
return videoPlayer.isPlaying() &&
|
||||
videoPlayer.initialSeekToStartTime === false;
|
||||
return state.videoPlayer.isPlaying() &&
|
||||
state.videoPlayer.initialSeekToStartTime === false;
|
||||
}, 'duration becomes available', WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(videoPlayer.startTime).toBe(START_TIME);
|
||||
expect(videoPlayer.endTime).toBe(END_TIME);
|
||||
expect(state.videoPlayer.startTime).toBe(START_TIME);
|
||||
expect(state.videoPlayer.endTime).toBe(END_TIME);
|
||||
|
||||
expect(videoPlayer.player.seekTo).toHaveBeenCalledWith(START_TIME);
|
||||
expect(state.videoPlayer.player.seekTo)
|
||||
.toHaveBeenCalledWith(START_TIME);
|
||||
|
||||
expect(videoProgressSlider.updateStartEndTimeRegion)
|
||||
expect(state.videoProgressSlider.updateStartEndTimeRegion)
|
||||
.toHaveBeenCalledWith({duration: duration});
|
||||
|
||||
expect(videoPlayer.seekToStartTimeOldSpeed).toBe(state.speed);
|
||||
expect(state.videoPlayer.seekToStartTimeOldSpeed)
|
||||
.toBe(state.speed);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('updatePlayTime with invalid endTime', function () {
|
||||
beforeEach(function () {
|
||||
initialize({end: 100000});
|
||||
state = jasmine.initializePlayer(
|
||||
{
|
||||
end: 100000
|
||||
}
|
||||
);
|
||||
|
||||
spyOn(videoPlayer, 'updatePlayTime').andCallThrough();
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoPlayer, 'updatePlayTime').andCallThrough();
|
||||
});
|
||||
|
||||
it('invalid endTime is reset to null', function () {
|
||||
var duration;
|
||||
|
||||
videoPlayer.updatePlayTime.reset();
|
||||
videoPlayer.play();
|
||||
state.videoPlayer.updatePlayTime.reset();
|
||||
state.videoPlayer.play();
|
||||
|
||||
waitsFor(function () {
|
||||
return videoPlayer.isPlaying() &&
|
||||
videoPlayer.initialSeekToStartTime === false;
|
||||
}, 'updatePlayTime was invoked and duration is set', WAIT_TIMEOUT);
|
||||
waitsFor(
|
||||
function () {
|
||||
return state.videoPlayer.isPlaying() &&
|
||||
state.videoPlayer.initialSeekToStartTime === false;
|
||||
},
|
||||
'updatePlayTime was invoked and duration is set',
|
||||
WAIT_TIMEOUT
|
||||
);
|
||||
|
||||
runs(function () {
|
||||
expect(videoPlayer.endTime).toBe(null);
|
||||
expect(state.videoPlayer.endTime).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -745,9 +748,12 @@
|
||||
describe('toggleFullScreen', function () {
|
||||
describe('when the video player is not full screen', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
spyOn(videoCaption, 'resize').andCallThrough();
|
||||
videoControl.toggleFullScreen(jQuery.Event('click'));
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoCaption, 'resize').andCallThrough();
|
||||
state.videoControl.toggleFullScreen(jQuery.Event('click'));
|
||||
});
|
||||
|
||||
it('replace the full screen button tooltip', function () {
|
||||
@@ -760,22 +766,25 @@
|
||||
});
|
||||
|
||||
it('tell VideoCaption to resize', function () {
|
||||
expect(videoCaption.resize).toHaveBeenCalled();
|
||||
expect(state.videoCaption.resize).toHaveBeenCalled();
|
||||
expect(state.resizer.setMode).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the video player already full screen', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
spyOn(videoCaption, 'resize').andCallThrough();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoCaption, 'resize').andCallThrough();
|
||||
|
||||
state.el.addClass('video-fullscreen');
|
||||
videoControl.fullScreenState = true;
|
||||
state.videoControl.fullScreenState = true;
|
||||
isFullScreen = true;
|
||||
videoControl.fullScreenEl.attr('title', 'Exit-fullscreen');
|
||||
state.videoControl.fullScreenEl.attr('title', 'Exit-fullscreen');
|
||||
|
||||
videoControl.toggleFullScreen(jQuery.Event('click'));
|
||||
state.videoControl.toggleFullScreen(jQuery.Event('click'));
|
||||
});
|
||||
|
||||
it('replace the full screen button tooltip', function () {
|
||||
@@ -788,7 +797,7 @@
|
||||
});
|
||||
|
||||
it('tell VideoCaption to resize', function () {
|
||||
expect(videoCaption.resize).toHaveBeenCalled();
|
||||
expect(state.videoCaption.resize).toHaveBeenCalled();
|
||||
expect(state.resizer.setMode)
|
||||
.toHaveBeenCalledWith('width');
|
||||
});
|
||||
@@ -797,112 +806,114 @@
|
||||
|
||||
describe('play', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
spyOn(player, 'playVideo').andCallThrough();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoPlayer.player, 'playVideo').andCallThrough();
|
||||
});
|
||||
|
||||
describe('when the player is not ready', function () {
|
||||
beforeEach(function () {
|
||||
player.playVideo = void 0;
|
||||
videoPlayer.play();
|
||||
state.videoPlayer.player.playVideo = void 0;
|
||||
state.videoPlayer.play();
|
||||
});
|
||||
|
||||
it('does nothing', function () {
|
||||
expect(player.playVideo).toBeUndefined();
|
||||
expect(state.videoPlayer.player.playVideo).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the player is ready', function () {
|
||||
beforeEach(function () {
|
||||
player.playVideo.andReturn(true);
|
||||
videoPlayer.play();
|
||||
state.videoPlayer.player.playVideo.andReturn(true);
|
||||
state.videoPlayer.play();
|
||||
});
|
||||
|
||||
it('delegate to the player', function () {
|
||||
expect(player.playVideo).toHaveBeenCalled();
|
||||
expect(state.videoPlayer.player.playVideo).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isPlaying', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
spyOn(player, 'getPlayerState').andCallThrough();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoPlayer.player, 'getPlayerState').andCallThrough();
|
||||
});
|
||||
|
||||
describe('when the video is playing', function () {
|
||||
beforeEach(function () {
|
||||
player.getPlayerState.andReturn(YT.PlayerState.PLAYING);
|
||||
state.videoPlayer.player.getPlayerState.andReturn(YT.PlayerState.PLAYING);
|
||||
});
|
||||
|
||||
it('return true', function () {
|
||||
expect(videoPlayer.isPlaying()).toBeTruthy();
|
||||
expect(state.videoPlayer.isPlaying()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the video is not playing', function () {
|
||||
beforeEach(function () {
|
||||
player.getPlayerState.andReturn(YT.PlayerState.PAUSED);
|
||||
state.videoPlayer.player.getPlayerState.andReturn(YT.PlayerState.PAUSED);
|
||||
});
|
||||
|
||||
it('return false', function () {
|
||||
expect(videoPlayer.isPlaying()).toBeFalsy();
|
||||
expect(state.videoPlayer.isPlaying()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('pause', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
spyOn(player, 'pauseVideo').andCallThrough();
|
||||
videoPlayer.pause();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoPlayer.player, 'pauseVideo').andCallThrough();
|
||||
state.videoPlayer.pause();
|
||||
});
|
||||
|
||||
it('delegate to the player', function () {
|
||||
expect(player.pauseVideo).toHaveBeenCalled();
|
||||
expect(state.videoPlayer.player.pauseVideo).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('duration', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
spyOn(player, 'getDuration').andCallThrough();
|
||||
videoPlayer.duration();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoPlayer.player, 'getDuration').andCallThrough();
|
||||
state.videoPlayer.duration();
|
||||
});
|
||||
|
||||
it('delegate to the player', function () {
|
||||
expect(player.getDuration).toHaveBeenCalled();
|
||||
expect(state.videoPlayer.player.getDuration).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDuration', function () {
|
||||
var oldYT;
|
||||
|
||||
beforeEach(function () {
|
||||
oldYT = window.YT;
|
||||
|
||||
// We need to make sure that metadata is returned via an AJAX
|
||||
// request. Without the jasmine.stubRequests() below we will
|
||||
// get the error:
|
||||
//
|
||||
// this.metadata[this.youtubeId(...)] is undefined
|
||||
jasmine.stubRequests();
|
||||
|
||||
window.YT = {
|
||||
Player: function () {
|
||||
return { getDuration: function () { return 60; } };
|
||||
},
|
||||
PlayerState: oldYT.PlayerState,
|
||||
ready: function (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
state = jasmine.initializePlayerYouTube();
|
||||
|
||||
spyOn(window.YT, 'Player').andCallThrough();
|
||||
|
||||
initializeYouTube();
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state, 'getDuration').andCallThrough();
|
||||
spyOn(state.videoPlayer.player, 'getDuration').andReturn(0);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
window.YT = oldYT;
|
||||
// When `state.videoPlayer.player.getDuration()` returns a `0`,
|
||||
// the fall-back function `state.getDuration()` will be called.
|
||||
state.videoPlayer.player.getDuration.andReturn(0);
|
||||
});
|
||||
|
||||
it('getDuration is called as a fall-back', function () {
|
||||
@@ -914,27 +925,33 @@
|
||||
|
||||
describe('playback rate', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
player.setPlaybackRate(1.5);
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
state.videoPlayer.player.setPlaybackRate(1.5);
|
||||
});
|
||||
|
||||
it('set the player playback rate', function () {
|
||||
expect(player.video.playbackRate).toEqual(1.5);
|
||||
expect(state.videoPlayer.player.video.playbackRate).toEqual(1.5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('volume', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
spyOn(player, 'getVolume').andCallThrough();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
spyOn(state.videoPlayer.player, 'getVolume').andCallThrough();
|
||||
});
|
||||
|
||||
it('set the player volume', function () {
|
||||
var expectedValue = 60,
|
||||
realValue;
|
||||
|
||||
player.setVolume(60);
|
||||
realValue = Math.round(player.getVolume()*100);
|
||||
state.videoPlayer.player.setVolume(60);
|
||||
realValue = Math.round(state.videoPlayer.player.getVolume()*100);
|
||||
|
||||
expect(realValue).toEqual(expectedValue);
|
||||
});
|
||||
@@ -942,9 +959,14 @@
|
||||
|
||||
describe('on Touch devices', function () {
|
||||
it('`is-touch` class name is added to container', function () {
|
||||
$.each(['iPad', 'Android', 'iPhone'], function(index, device) {
|
||||
$.each(
|
||||
['iPad', 'Android', 'iPhone'],
|
||||
function (index, device)
|
||||
{
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
expect(state.el).toHaveClass('is-touch');
|
||||
});
|
||||
@@ -952,11 +974,13 @@
|
||||
|
||||
it('modules are not initialized on iPhone', function () {
|
||||
window.onTouchBasedDevice.andReturn(['iPhone']);
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
var modules = [
|
||||
videoControl, videoCaption, videoProgressSlider,
|
||||
videoSpeedControl, videoVolumeControl
|
||||
state.videoControl, state.videoCaption, state.videoProgressSlider,
|
||||
state.videoSpeedControl, state.videoVolumeControl
|
||||
];
|
||||
|
||||
$.each(modules, function (index, module) {
|
||||
@@ -964,37 +988,42 @@
|
||||
});
|
||||
});
|
||||
|
||||
$.each(['iPad', 'Android'], function(index, device) {
|
||||
var message = 'controls become visible after playing starts on ' +
|
||||
device;
|
||||
it(message, function() {
|
||||
var controls;
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
$.each(['iPad', 'Android'], function (index, device) {
|
||||
var message = 'controls become visible after playing starts ' +
|
||||
'on ' + device;
|
||||
|
||||
runs(function () {
|
||||
initialize();
|
||||
controls = state.el.find('.video-controls');
|
||||
it(message, function () {
|
||||
var controls;
|
||||
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
|
||||
runs(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
state.videoEl = $('video, iframe');
|
||||
|
||||
controls = state.el.find('.video-controls');
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return state.el.hasClass('is-initialized');
|
||||
},'Video is not initialized.' , WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(controls).toHaveClass('is-hidden');
|
||||
state.videoPlayer.play();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
duration = state.videoPlayer.duration();
|
||||
|
||||
return duration > 0 && state.videoPlayer.isPlaying();
|
||||
},'Video does not play.' , WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(controls).not.toHaveClass('is-hidden');
|
||||
});
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return state.el.hasClass('is-initialized');
|
||||
},'Video is not initialized.' , WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(controls).toHaveClass('is-hidden');
|
||||
videoPlayer.play();
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
duration = videoPlayer.duration();
|
||||
|
||||
return duration > 0 && videoPlayer.isPlaying();
|
||||
},'Video does not play.' , WAIT_TIMEOUT);
|
||||
|
||||
runs(function () {
|
||||
expect(controls).not.toHaveClass('is-hidden');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,84 +1,81 @@
|
||||
(function() {
|
||||
describe('VideoProgressSlider', function() {
|
||||
var state, videoPlayer, videoProgressSlider, oldOTBD;
|
||||
(function (undefined) {
|
||||
describe('VideoProgressSlider', function () {
|
||||
var state, oldOTBD;
|
||||
|
||||
function initialize() {
|
||||
loadFixtures('video_all.html');
|
||||
state = new Video('#example');
|
||||
videoPlayer = state.videoPlayer;
|
||||
videoProgressSlider = state.videoProgressSlider;
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice')
|
||||
.andReturn(null);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
afterEach(function () {
|
||||
$('source').remove();
|
||||
window.onTouchBasedDevice = oldOTBD;
|
||||
});
|
||||
|
||||
describe('constructor', function() {
|
||||
describe('on a non-touch based device', function() {
|
||||
beforeEach(function() {
|
||||
describe('constructor', function () {
|
||||
describe('on a non-touch based device', function () {
|
||||
beforeEach(function () {
|
||||
spyOn($.fn, 'slider').andCallThrough();
|
||||
initialize();
|
||||
|
||||
state = jasmine.initializePlayer();
|
||||
});
|
||||
|
||||
it('build the slider', function() {
|
||||
expect(videoProgressSlider.slider).toBe('.slider');
|
||||
it('build the slider', function () {
|
||||
expect(state.videoProgressSlider.slider).toBe('.slider');
|
||||
expect($.fn.slider).toHaveBeenCalledWith({
|
||||
range: 'min',
|
||||
change: videoProgressSlider.onChange,
|
||||
slide: videoProgressSlider.onSlide,
|
||||
stop: videoProgressSlider.onStop
|
||||
change: state.videoProgressSlider.onChange,
|
||||
slide: state.videoProgressSlider.onSlide,
|
||||
stop: state.videoProgressSlider.onStop
|
||||
});
|
||||
});
|
||||
|
||||
it('build the seek handle', function() {
|
||||
expect(videoProgressSlider.handle)
|
||||
it('build the seek handle', function () {
|
||||
expect(state.videoProgressSlider.handle)
|
||||
.toBe('.slider .ui-slider-handle');
|
||||
});
|
||||
});
|
||||
|
||||
describe('on a touch-based device', function() {
|
||||
it('does not build the slider on iPhone', function() {
|
||||
describe('on a touch-based device', function () {
|
||||
it('does not build the slider on iPhone', function () {
|
||||
|
||||
window.onTouchBasedDevice.andReturn(['iPhone']);
|
||||
initialize();
|
||||
|
||||
expect(videoProgressSlider).toBeUndefined();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
expect(state.videoProgressSlider).toBeUndefined();
|
||||
|
||||
// We can't expect $.fn.slider not to have been called,
|
||||
// because sliders are used in other parts of Video.
|
||||
});
|
||||
$.each(['iPad', 'Android'], function(index, device) {
|
||||
it('build the slider on ' + device, function() {
|
||||
$.each(['iPad', 'Android'], function (index, device) {
|
||||
it('build the slider on ' + device, function () {
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
initialize();
|
||||
expect(videoProgressSlider.slider).toBeDefined();
|
||||
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
expect(state.videoProgressSlider.slider).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('play', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
describe('play', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
});
|
||||
|
||||
describe('when the slider was already built', function() {
|
||||
describe('when the slider was already built', function () {
|
||||
var spy;
|
||||
|
||||
beforeEach(function() {
|
||||
spy = spyOn(videoProgressSlider, 'buildSlider');
|
||||
beforeEach(function () {
|
||||
spy = spyOn(state.videoProgressSlider, 'buildSlider');
|
||||
spy.andCallThrough();
|
||||
videoPlayer.play();
|
||||
state.videoPlayer.play();
|
||||
});
|
||||
|
||||
it('does not build the slider', function() {
|
||||
it('does not build the slider', function () {
|
||||
expect(spy.callCount).toEqual(0);
|
||||
});
|
||||
});
|
||||
@@ -86,40 +83,40 @@
|
||||
// Currently, the slider is not rebuilt if it does not exist.
|
||||
});
|
||||
|
||||
describe('updatePlayTime', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
describe('updatePlayTime', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
});
|
||||
|
||||
describe('when frozen', function() {
|
||||
beforeEach(function() {
|
||||
describe('when frozen', function () {
|
||||
beforeEach(function () {
|
||||
spyOn($.fn, 'slider').andCallThrough();
|
||||
videoProgressSlider.frozen = true;
|
||||
videoProgressSlider.updatePlayTime(20, 120);
|
||||
state.videoProgressSlider.frozen = true;
|
||||
state.videoProgressSlider.updatePlayTime(20, 120);
|
||||
});
|
||||
|
||||
it('does not update the slider', function() {
|
||||
it('does not update the slider', function () {
|
||||
expect($.fn.slider).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when not frozen', function() {
|
||||
beforeEach(function() {
|
||||
describe('when not frozen', function () {
|
||||
beforeEach(function () {
|
||||
spyOn($.fn, 'slider').andCallThrough();
|
||||
videoProgressSlider.frozen = false;
|
||||
videoProgressSlider.updatePlayTime({
|
||||
state.videoProgressSlider.frozen = false;
|
||||
state.videoProgressSlider.updatePlayTime({
|
||||
time: 20,
|
||||
duration: 120
|
||||
});
|
||||
});
|
||||
|
||||
it('update the max value of the slider', function() {
|
||||
it('update the max value of the slider', function () {
|
||||
expect($.fn.slider).toHaveBeenCalledWith(
|
||||
'option', 'max', 120
|
||||
);
|
||||
});
|
||||
|
||||
it('update current value of the slider', function() {
|
||||
it('update current value of the slider', function () {
|
||||
expect($.fn.slider).toHaveBeenCalledWith(
|
||||
'option', 'value', 20
|
||||
);
|
||||
@@ -127,72 +124,74 @@
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSlide', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
describe('onSlide', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
spyOn($.fn, 'slider').andCallThrough();
|
||||
spyOn(videoPlayer, 'onSlideSeek').andCallThrough();
|
||||
spyOn(state.videoPlayer, 'onSlideSeek').andCallThrough();
|
||||
});
|
||||
|
||||
// Disabled 12/30/13 due to flakiness in master
|
||||
xit('freeze the slider', function() {
|
||||
videoProgressSlider.onSlide(
|
||||
xit('freeze the slider', function () {
|
||||
state.videoProgressSlider.onSlide(
|
||||
jQuery.Event('slide'), { value: 20 }
|
||||
);
|
||||
|
||||
expect(videoProgressSlider.frozen).toBeTruthy();
|
||||
expect(state.videoProgressSlider.frozen).toBeTruthy();
|
||||
});
|
||||
|
||||
// Disabled 12/30/13 due to flakiness in master
|
||||
xit('trigger seek event', function() {
|
||||
videoProgressSlider.onSlide(
|
||||
xit('trigger seek event', function () {
|
||||
state.videoProgressSlider.onSlide(
|
||||
jQuery.Event('slide'), { value: 20 }
|
||||
);
|
||||
|
||||
expect(videoPlayer.onSlideSeek).toHaveBeenCalled();
|
||||
expect(state.videoPlayer.onSlideSeek).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onStop', function() {
|
||||
describe('onStop', function () {
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
jasmine.Clock.useMock();
|
||||
|
||||
initialize();
|
||||
spyOn(videoPlayer, 'onSlideSeek').andCallThrough();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
spyOn(state.videoPlayer, 'onSlideSeek').andCallThrough();
|
||||
});
|
||||
|
||||
// Disabled 12/30/13 due to flakiness in master
|
||||
xit('freeze the slider', function() {
|
||||
videoProgressSlider.onStop(
|
||||
xit('freeze the slider', function () {
|
||||
state.videoProgressSlider.onStop(
|
||||
jQuery.Event('stop'), { value: 20 }
|
||||
);
|
||||
|
||||
expect(videoProgressSlider.frozen).toBeTruthy();
|
||||
expect(state.videoProgressSlider.frozen).toBeTruthy();
|
||||
});
|
||||
|
||||
// Disabled 12/30/13 due to flakiness in master
|
||||
xit('trigger seek event', function() {
|
||||
videoProgressSlider.onStop(
|
||||
xit('trigger seek event', function () {
|
||||
state.videoProgressSlider.onStop(
|
||||
jQuery.Event('stop'), { value: 20 }
|
||||
);
|
||||
|
||||
expect(videoPlayer.onSlideSeek).toHaveBeenCalled();
|
||||
expect(state.videoPlayer.onSlideSeek).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
// Disabled 12/30/13 due to flakiness in master
|
||||
xit('set timeout to unfreeze the slider', function() {
|
||||
videoProgressSlider.onStop(
|
||||
xit('set timeout to unfreeze the slider', function () {
|
||||
state.videoProgressSlider.onStop(
|
||||
jQuery.Event('stop'), { value: 20 }
|
||||
);
|
||||
|
||||
jasmine.Clock.tick(200);
|
||||
|
||||
expect(videoProgressSlider.frozen).toBeFalsy();
|
||||
expect(state.videoProgressSlider.frozen).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('getRangeParams' , function() {
|
||||
it('getRangeParams' , function () {
|
||||
var testCases = [
|
||||
{
|
||||
startTime: 10,
|
||||
@@ -211,9 +210,9 @@
|
||||
}
|
||||
];
|
||||
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
$.each(testCases, function(index, testCase) {
|
||||
$.each(testCases, function (index, testCase) {
|
||||
var step = 100/testCase.duration,
|
||||
left = testCase.startTime*step,
|
||||
width = testCase.endTime*step - left,
|
||||
@@ -221,7 +220,7 @@
|
||||
left: left + '%',
|
||||
width: width + '%'
|
||||
},
|
||||
params = videoProgressSlider.getRangeParams(
|
||||
params = state.videoProgressSlider.getRangeParams(
|
||||
testCase.startTime, testCase.endTime, testCase.duration
|
||||
);
|
||||
|
||||
@@ -231,40 +230,44 @@
|
||||
|
||||
describe('notifyThroughHandleEnd', function () {
|
||||
beforeEach(function () {
|
||||
initialize();
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
spyOnEvent(videoProgressSlider.handle, 'focus');
|
||||
spyOn(videoProgressSlider, 'notifyThroughHandleEnd')
|
||||
spyOnEvent(state.videoProgressSlider.handle, 'focus');
|
||||
spyOn(state.videoProgressSlider, 'notifyThroughHandleEnd')
|
||||
.andCallThrough();
|
||||
});
|
||||
|
||||
it('params.end = true', function () {
|
||||
videoProgressSlider.notifyThroughHandleEnd({end: true});
|
||||
state.videoProgressSlider.notifyThroughHandleEnd({end: true});
|
||||
|
||||
expect(videoProgressSlider.handle.attr('title'))
|
||||
expect(state.videoProgressSlider.handle.attr('title'))
|
||||
.toBe('video ended');
|
||||
|
||||
expect('focus').toHaveBeenTriggeredOn(videoProgressSlider.handle);
|
||||
expect('focus').toHaveBeenTriggeredOn(
|
||||
state.videoProgressSlider.handle
|
||||
);
|
||||
});
|
||||
|
||||
it('params.end = false', function () {
|
||||
videoProgressSlider.notifyThroughHandleEnd({end: false});
|
||||
state.videoProgressSlider.notifyThroughHandleEnd({end: false});
|
||||
|
||||
expect(videoProgressSlider.handle.attr('title'))
|
||||
expect(state.videoProgressSlider.handle.attr('title'))
|
||||
.toBe('video position');
|
||||
|
||||
expect('focus').not.toHaveBeenTriggeredOn(videoProgressSlider.handle);
|
||||
expect('focus').not.toHaveBeenTriggeredOn(
|
||||
state.videoProgressSlider.handle
|
||||
);
|
||||
});
|
||||
|
||||
it('is called when video plays', function () {
|
||||
videoPlayer.play();
|
||||
state.videoPlayer.play();
|
||||
|
||||
waitsFor(function () {
|
||||
return videoPlayer.isPlaying();
|
||||
return state.videoPlayer.isPlaying();
|
||||
}, 'duration is set, video is playing', 5000);
|
||||
|
||||
runs(function () {
|
||||
expect(videoProgressSlider.notifyThroughHandleEnd)
|
||||
expect(state.videoProgressSlider.notifyThroughHandleEnd)
|
||||
.toHaveBeenCalledWith({end: false});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,64 +1,45 @@
|
||||
(function() {
|
||||
describe('VideoQualityControl', function() {
|
||||
var state, videoControl, videoQualityControl, oldOTBD;
|
||||
(function (undefined) {
|
||||
describe('VideoQualityControl', function () {
|
||||
var state, oldOTBD;
|
||||
|
||||
function initialize() {
|
||||
loadFixtures('video.html');
|
||||
state = new Video('#example');
|
||||
videoControl = state.videoControl;
|
||||
videoQualityControl = state.videoQualityControl;
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine
|
||||
.createSpy('onTouchBasedDevice')
|
||||
.andReturn(null);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
$('source').remove();
|
||||
window.onTouchBasedDevice = oldOTBD;
|
||||
});
|
||||
|
||||
describe('constructor', function() {
|
||||
var oldYT = window.YT;
|
||||
|
||||
beforeEach(function() {
|
||||
window.YT = {
|
||||
Player: function () {
|
||||
return { getDuration: function () { return 60; } };
|
||||
},
|
||||
PlayerState: oldYT.PlayerState,
|
||||
ready: function(f){f();}
|
||||
};
|
||||
|
||||
initialize();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
window.YT = oldYT;
|
||||
});
|
||||
|
||||
it('render the quality control', function() {
|
||||
var container = videoControl.secondaryControlsEl;
|
||||
expect(container).toContain('a.quality_control');
|
||||
});
|
||||
|
||||
it('add ARIA attributes to quality control', function () {
|
||||
var qualityControl = $('a.quality_control');
|
||||
expect(qualityControl).toHaveAttrs({
|
||||
'role': 'button',
|
||||
'title': 'HD off',
|
||||
'aria-disabled': 'false'
|
||||
beforeEach(function () {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine
|
||||
.createSpy('onTouchBasedDevice')
|
||||
.andReturn(null);
|
||||
});
|
||||
});
|
||||
|
||||
it('bind the quality control', function() {
|
||||
var handler = videoQualityControl.toggleQuality;
|
||||
expect($('a.quality_control')).toHandleWith('click', handler);
|
||||
});
|
||||
afterEach(function () {
|
||||
$('source').remove();
|
||||
window.onTouchBasedDevice = oldOTBD;
|
||||
});
|
||||
|
||||
describe('constructor', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer('video.html');
|
||||
});
|
||||
|
||||
it('render the quality control', function () {
|
||||
var container = state.videoControl.secondaryControlsEl;
|
||||
|
||||
expect(container).toContain('a.quality_control');
|
||||
});
|
||||
|
||||
it('add ARIA attributes to quality control', function () {
|
||||
var qualityControl = $('a.quality_control');
|
||||
|
||||
expect(qualityControl).toHaveAttrs({
|
||||
'role': 'button',
|
||||
'title': 'HD off',
|
||||
'aria-disabled': 'false'
|
||||
});
|
||||
});
|
||||
|
||||
it('bind the quality control', function () {
|
||||
var handler = state.videoQualityControl.toggleQuality;
|
||||
|
||||
expect($('a.quality_control')).toHandleWith('click', handler);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,183 +1,208 @@
|
||||
(function() {
|
||||
describe('VideoSpeedControl', function() {
|
||||
var state, videoPlayer, videoControl, videoSpeedControl;
|
||||
(function (undefined) {
|
||||
describe('VideoSpeedControl', function () {
|
||||
var state, oldOTBD;
|
||||
|
||||
function initialize() {
|
||||
loadFixtures('video_all.html');
|
||||
state = new Video('#example');
|
||||
videoPlayer = state.videoPlayer;
|
||||
videoControl = state.videoControl;
|
||||
videoSpeedControl = state.videoSpeedControl;
|
||||
}
|
||||
beforeEach(function () {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice')
|
||||
.andReturn(null);
|
||||
});
|
||||
|
||||
beforeEach(function() {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn(null);
|
||||
afterEach(function () {
|
||||
$('source').remove();
|
||||
window.onTouchBasedDevice = oldOTBD;
|
||||
});
|
||||
|
||||
describe('constructor', function () {
|
||||
describe('always', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
});
|
||||
|
||||
it('add the video speed control to player', function () {
|
||||
var li, secondaryControls;
|
||||
|
||||
secondaryControls = $('.secondary-controls');
|
||||
li = secondaryControls.find('.video_speeds li');
|
||||
|
||||
expect(secondaryControls).toContain('.speeds');
|
||||
expect(secondaryControls).toContain('.video_speeds');
|
||||
expect(secondaryControls.find('p.active').text())
|
||||
.toBe('1.0x');
|
||||
expect(li.filter('.active')).toHaveData(
|
||||
'speed', state.videoSpeedControl.currentSpeed
|
||||
);
|
||||
expect(li.length).toBe(state.videoSpeedControl.speeds.length);
|
||||
|
||||
$.each(li.toArray().reverse(), function (index, link) {
|
||||
expect($(link)).toHaveData(
|
||||
'speed', state.videoSpeedControl.speeds[index]
|
||||
);
|
||||
expect($(link).find('a').text()).toBe(
|
||||
state.videoSpeedControl.speeds[index] + 'x'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('add ARIA attributes to speed control', function () {
|
||||
var speedControl = $('div.speeds>a');
|
||||
|
||||
expect(speedControl).toHaveAttrs({
|
||||
'role': 'button',
|
||||
'title': 'Speeds',
|
||||
'aria-disabled': 'false'
|
||||
});
|
||||
});
|
||||
|
||||
it('bind to change video speed link', function () {
|
||||
expect($('.video_speeds a')).toHandleWith(
|
||||
'click', state.videoSpeedControl.changeVideoSpeed
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when running on touch based device', function () {
|
||||
$.each(['iPad', 'Android'], function (index, device) {
|
||||
it('is not rendered on' + device, function () {
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
state = jasmine.initializePlayer();
|
||||
|
||||
expect(state.el.find('div.speeds')).not.toExist();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when running on non-touch based device', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
});
|
||||
|
||||
it('open the speed toggle on hover', function () {
|
||||
$('.speeds').mouseenter();
|
||||
expect($('.speeds')).toHaveClass('open');
|
||||
|
||||
$('.speeds').mouseleave();
|
||||
expect($('.speeds')).not.toHaveClass('open');
|
||||
});
|
||||
|
||||
it('close the speed toggle on mouse out', function () {
|
||||
$('.speeds').mouseenter().mouseleave();
|
||||
|
||||
expect($('.speeds')).not.toHaveClass('open');
|
||||
});
|
||||
|
||||
it('close the speed toggle on click', function () {
|
||||
$('.speeds').mouseenter().click();
|
||||
|
||||
expect($('.speeds')).not.toHaveClass('open');
|
||||
});
|
||||
|
||||
// Tabbing depends on the following order:
|
||||
// 1. Play anchor
|
||||
// 2. Speed anchor
|
||||
// 3. A number of speed entry anchors
|
||||
// 4. Volume anchor
|
||||
// If another focusable element is inserted or if the order is
|
||||
// changed, things will malfunction as a flag,
|
||||
// state.previousFocus, is set in the 1,3,4 elements and is
|
||||
// used to determine the behavior of foucus() and blur() for
|
||||
// the speed anchor.
|
||||
it(
|
||||
'checks for a certain order in focusable elements in ' +
|
||||
'video controls',
|
||||
function ()
|
||||
{
|
||||
var foundFirst = false,
|
||||
playIndex, speedIndex, firstSpeedEntry, lastSpeedEntry,
|
||||
volumeIndex;
|
||||
|
||||
$('.video-controls').find('a, :focusable').each(
|
||||
function (index)
|
||||
{
|
||||
if ($(this).hasClass('video_control')) {
|
||||
playIndex = index;
|
||||
} else if ($(this).parent().hasClass('speeds')) {
|
||||
speedIndex = index;
|
||||
} else if ($(this).hasClass('speed_link')) {
|
||||
if (!foundFirst) {
|
||||
firstSpeedEntry = index;
|
||||
foundFirst = true;
|
||||
}
|
||||
|
||||
lastSpeedEntry = index;
|
||||
} else if ($(this).parent().hasClass('volume')) {
|
||||
volumeIndex = index;
|
||||
}
|
||||
});
|
||||
|
||||
expect(playIndex+1).toEqual(speedIndex);
|
||||
expect(speedIndex+1).toEqual(firstSpeedEntry);
|
||||
expect(lastSpeedEntry+1).toEqual(volumeIndex);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('changeVideoSpeed', function () {
|
||||
// This is an unnecessary test. The internal browser API, and
|
||||
// YouTube API detect (and do not do anything) if there is a
|
||||
// request for a speed that is already set.
|
||||
//
|
||||
// describe("when new speed is the same") ...
|
||||
|
||||
describe('when new speed is not the same', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
state.videoSpeedControl.setSpeed(1.0);
|
||||
spyOn(state.videoPlayer, 'onSpeedChange').andCallThrough();
|
||||
|
||||
$('li[data-speed="0.75"] a').click();
|
||||
});
|
||||
|
||||
it('trigger speedChange event', function () {
|
||||
expect(state.videoPlayer.onSpeedChange).toHaveBeenCalled();
|
||||
expect(state.videoSpeedControl.currentSpeed).toEqual(0.75);
|
||||
});
|
||||
});
|
||||
|
||||
describe(
|
||||
'make sure the speed control gets the focus afterwards',
|
||||
function ()
|
||||
{
|
||||
var anchor;
|
||||
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
anchor= $('.speeds > a').first();
|
||||
state.videoSpeedControl.setSpeed(1.0);
|
||||
spyOnEvent(anchor, 'focus');
|
||||
});
|
||||
|
||||
it('when the speed is the same', function () {
|
||||
$('li[data-speed="1.0"] a').click();
|
||||
expect('focus').toHaveBeenTriggeredOn(anchor);
|
||||
});
|
||||
|
||||
it('when the speed is not the same', function () {
|
||||
$('li[data-speed="0.75"] a').click();
|
||||
expect('focus').toHaveBeenTriggeredOn(anchor);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSpeedChange', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
$('li[data-speed="1.0"] a').addClass('active');
|
||||
state.videoSpeedControl.setSpeed(0.75);
|
||||
});
|
||||
|
||||
it('set the new speed as active', function () {
|
||||
expect($('.video_speeds li[data-speed="1.0"]'))
|
||||
.not.toHaveClass('active');
|
||||
expect($('.video_speeds li[data-speed="0.75"]'))
|
||||
.toHaveClass('active');
|
||||
expect($('.speeds p.active')).toHaveHtml('0.75x');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
afterEach(function() {
|
||||
$('source').remove();
|
||||
window.onTouchBasedDevice = oldOTBD;
|
||||
});
|
||||
|
||||
describe('constructor', function() {
|
||||
describe('always', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
});
|
||||
|
||||
it('add the video speed control to player', function() {
|
||||
var li, secondaryControls;
|
||||
secondaryControls = $('.secondary-controls');
|
||||
li = secondaryControls.find('.video_speeds li');
|
||||
expect(secondaryControls).toContain('.speeds');
|
||||
expect(secondaryControls).toContain('.video_speeds');
|
||||
expect(secondaryControls.find('p.active').text()).toBe('1.0x');
|
||||
expect(li.filter('.active')).toHaveData('speed', videoSpeedControl.currentSpeed);
|
||||
expect(li.length).toBe(videoSpeedControl.speeds.length);
|
||||
$.each(li.toArray().reverse(), function(index, link) {
|
||||
expect($(link)).toHaveData('speed', videoSpeedControl.speeds[index]);
|
||||
expect($(link).find('a').text()).toBe(videoSpeedControl.speeds[index] + 'x');
|
||||
});
|
||||
});
|
||||
|
||||
it('add ARIA attributes to speed control', function () {
|
||||
var speedControl = $('div.speeds>a');
|
||||
expect(speedControl).toHaveAttrs({
|
||||
'role': 'button',
|
||||
'title': 'Speeds',
|
||||
'aria-disabled': 'false'
|
||||
});
|
||||
});
|
||||
|
||||
it('bind to change video speed link', function() {
|
||||
expect($('.video_speeds a')).toHandleWith('click', videoSpeedControl.changeVideoSpeed);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when running on touch based device', function() {
|
||||
$.each(['iPad', 'Android'], function(index, device) {
|
||||
it('is not rendered on' + device, function() {
|
||||
window.onTouchBasedDevice.andReturn([device]);
|
||||
initialize();
|
||||
expect(state.el.find('div.speeds')).not.toExist();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when running on non-touch based device', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
});
|
||||
|
||||
it('open the speed toggle on hover', function() {
|
||||
$('.speeds').mouseenter();
|
||||
expect($('.speeds')).toHaveClass('open');
|
||||
$('.speeds').mouseleave();
|
||||
expect($('.speeds')).not.toHaveClass('open');
|
||||
});
|
||||
|
||||
it('close the speed toggle on mouse out', function() {
|
||||
$('.speeds').mouseenter().mouseleave();
|
||||
expect($('.speeds')).not.toHaveClass('open');
|
||||
});
|
||||
|
||||
it('close the speed toggle on click', function() {
|
||||
$('.speeds').mouseenter().click();
|
||||
expect($('.speeds')).not.toHaveClass('open');
|
||||
});
|
||||
// Tabbing depends on the following order:
|
||||
// 1. Play anchor
|
||||
// 2. Speed anchor
|
||||
// 3. A number of speed entry anchors
|
||||
// 4. Volume anchor
|
||||
// If another focusable element is inserted or if the order is changed, things will
|
||||
// malfunction as a flag, state.previousFocus, is set in the 1,3,4 elements and is
|
||||
// used to determine the behavior of foucus() and blur() for the speed anchor.
|
||||
it('checks for a certain order in focusable elements in video controls', function() {
|
||||
var playIndex, speedIndex, firstSpeedEntry, lastSpeedEntry, volumeIndex, foundFirst = false;
|
||||
$('.video-controls').find('a, :focusable').each(function(index) {
|
||||
if ($(this).hasClass('video_control')) {
|
||||
playIndex = index;
|
||||
}
|
||||
else if ($(this).parent().hasClass('speeds')) {
|
||||
speedIndex = index;
|
||||
}
|
||||
else if ($(this).hasClass('speed_link')) {
|
||||
if (!foundFirst) {
|
||||
firstSpeedEntry = index;
|
||||
foundFirst = true;
|
||||
}
|
||||
lastSpeedEntry = index;
|
||||
}
|
||||
else if ($(this).parent().hasClass('volume')) {
|
||||
volumeIndex = index;
|
||||
}
|
||||
});
|
||||
expect(playIndex+1).toEqual(speedIndex);
|
||||
expect(speedIndex+1).toEqual(firstSpeedEntry);
|
||||
expect(lastSpeedEntry+1).toEqual(volumeIndex);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('changeVideoSpeed', function() {
|
||||
// This is an unnecessary test. The internal browser API, and YouTube API
|
||||
// detect (and do not do anything) if there is a request for a speed that
|
||||
// is already set.
|
||||
//
|
||||
// describe("when new speed is the same") ...
|
||||
|
||||
describe('when new speed is not the same', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
videoSpeedControl.setSpeed(1.0);
|
||||
spyOn(videoPlayer, 'onSpeedChange').andCallThrough();
|
||||
|
||||
$('li[data-speed="0.75"] a').click();
|
||||
});
|
||||
|
||||
it('trigger speedChange event', function() {
|
||||
expect(videoPlayer.onSpeedChange).toHaveBeenCalled();
|
||||
expect(videoSpeedControl.currentSpeed).toEqual(0.75);
|
||||
});
|
||||
});
|
||||
|
||||
describe('make sure the speed control gets the focus afterwards', function() {
|
||||
var anchor;
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
anchor= $('.speeds > a').first();
|
||||
videoSpeedControl.setSpeed(1.0);
|
||||
spyOnEvent(anchor, 'focus');
|
||||
});
|
||||
|
||||
it('when the speed is the same', function() {
|
||||
$('li[data-speed="1.0"] a').click();
|
||||
expect('focus').toHaveBeenTriggeredOn(anchor);
|
||||
});
|
||||
|
||||
it('when the speed is not the same', function() {
|
||||
$('li[data-speed="0.75"] a').click();
|
||||
expect('focus').toHaveBeenTriggeredOn(anchor);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSpeedChange', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
$('li[data-speed="1.0"] a').addClass('active');
|
||||
videoSpeedControl.setSpeed(0.75);
|
||||
});
|
||||
|
||||
it('set the new speed as active', function() {
|
||||
expect($('.video_speeds li[data-speed="1.0"]')).not.toHaveClass('active');
|
||||
expect($('.video_speeds li[data-speed="0.75"]')).toHaveClass('active');
|
||||
expect($('.speeds p.active')).toHaveHtml('0.75x');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,212 +1,209 @@
|
||||
(function() {
|
||||
describe('VideoVolumeControl', function() {
|
||||
var state, videoControl, videoVolumeControl, oldOTBD;
|
||||
(function (undefined) {
|
||||
describe('VideoVolumeControl', function () {
|
||||
var state, oldOTBD;
|
||||
|
||||
function initialize() {
|
||||
loadFixtures('video_all.html');
|
||||
state = new Video('#example');
|
||||
videoControl = state.videoControl;
|
||||
videoVolumeControl = state.videoVolumeControl;
|
||||
}
|
||||
beforeEach(function () {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice')
|
||||
.andReturn(null);
|
||||
|
||||
beforeEach(function() {
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn(null);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
$('source').remove();
|
||||
window.onTouchBasedDevice = oldOTBD;
|
||||
});
|
||||
|
||||
describe('constructor', function() {
|
||||
beforeEach(function() {
|
||||
spyOn($.fn, 'slider').andCallThrough();
|
||||
$.cookie.andReturn('75');
|
||||
initialize();
|
||||
});
|
||||
|
||||
it('initialize currentVolume to 75', function() {
|
||||
expect(state.videoVolumeControl.currentVolume).toEqual(75);
|
||||
});
|
||||
|
||||
it('render the volume control', function() {
|
||||
expect(videoControl.secondaryControlsEl.html()).toContain("<div class=\"volume\">\n");
|
||||
});
|
||||
|
||||
it('create the slider', function() {
|
||||
expect($.fn.slider).toHaveBeenCalledWith({
|
||||
orientation: "vertical",
|
||||
range: "min",
|
||||
min: 0,
|
||||
max: 100,
|
||||
value: videoVolumeControl.currentVolume,
|
||||
change: videoVolumeControl.onChange,
|
||||
slide: videoVolumeControl.onChange
|
||||
});
|
||||
});
|
||||
|
||||
it('add ARIA attributes to slider handle', function () {
|
||||
var sliderHandle = $('div.volume-slider>a.ui-slider-handle'),
|
||||
arr = ['muted', 'very low', 'low', 'average', 'loud', 'very loud',
|
||||
'maximum'];
|
||||
expect(sliderHandle).toHaveAttrs({
|
||||
'role': 'slider',
|
||||
'title': 'volume',
|
||||
'aria-disabled': 'false',
|
||||
'aria-valuemin': '0',
|
||||
'aria-valuemax': '100'
|
||||
});
|
||||
expect(sliderHandle.attr('aria-valuenow')).toBeInRange(0, 100);
|
||||
expect(sliderHandle.attr('aria-valuetext')).toBeInArray(arr);
|
||||
|
||||
});
|
||||
|
||||
it('add ARIA attributes to volume control', function () {
|
||||
var volumeControl = $('div.volume>a');
|
||||
expect(volumeControl).toHaveAttrs({
|
||||
'role': 'button',
|
||||
'title': 'Volume',
|
||||
'aria-disabled': 'false'
|
||||
});
|
||||
});
|
||||
|
||||
it('bind the volume control', function() {
|
||||
expect($('.volume>a')).toHandleWith('click', videoVolumeControl.toggleMute);
|
||||
expect($('.volume')).not.toHaveClass('open');
|
||||
$('.volume').mouseenter();
|
||||
expect($('.volume')).toHaveClass('open');
|
||||
$('.volume').mouseleave();
|
||||
expect($('.volume')).not.toHaveClass('open');
|
||||
});
|
||||
});
|
||||
|
||||
describe('onChange', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
});
|
||||
|
||||
describe('when the new volume is more than 0', function() {
|
||||
beforeEach(function() {
|
||||
videoVolumeControl.onChange(void 0, {
|
||||
value: 60
|
||||
});
|
||||
afterEach(function () {
|
||||
$('source').remove();
|
||||
window.onTouchBasedDevice = oldOTBD;
|
||||
});
|
||||
|
||||
it('set the player volume', function() {
|
||||
expect(videoVolumeControl.currentVolume).toEqual(60);
|
||||
});
|
||||
|
||||
it('remote muted class', function() {
|
||||
expect($('.volume')).not.toHaveClass('muted');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the new volume is 0', function() {
|
||||
beforeEach(function() {
|
||||
videoVolumeControl.onChange(void 0, {
|
||||
value: 0
|
||||
});
|
||||
});
|
||||
|
||||
it('set the player volume', function() {
|
||||
expect(videoVolumeControl.currentVolume).toEqual(0);
|
||||
});
|
||||
|
||||
it('add muted class', function() {
|
||||
expect($('.volume')).toHaveClass('muted');
|
||||
});
|
||||
});
|
||||
|
||||
var initialData = [
|
||||
{
|
||||
range: 'muted',
|
||||
value: 0,
|
||||
expectation: 'muted'
|
||||
},
|
||||
{
|
||||
range: 'in ]0,20]',
|
||||
value: 10,
|
||||
expectation: 'very low'
|
||||
},
|
||||
{
|
||||
range: 'in ]20,40]',
|
||||
value: 30,
|
||||
expectation: 'low'
|
||||
},
|
||||
{
|
||||
range: 'in ]40,60]',
|
||||
value: 50,
|
||||
expectation: 'average'
|
||||
},
|
||||
{
|
||||
range: 'in ]60,80]',
|
||||
value: 70,
|
||||
expectation: 'loud'
|
||||
},
|
||||
{
|
||||
range: 'in ]80,100[',
|
||||
value: 90,
|
||||
expectation: 'very loud'
|
||||
},
|
||||
{
|
||||
range: 'maximum',
|
||||
value: 100,
|
||||
expectation: 'maximum'
|
||||
}
|
||||
];
|
||||
|
||||
$.each(initialData, function(index, data) {
|
||||
describe('when the new volume is ' + data.range, function() {
|
||||
beforeEach(function() {
|
||||
videoVolumeControl.onChange(void 0, {
|
||||
value: data.value
|
||||
describe('constructor', function () {
|
||||
beforeEach(function () {
|
||||
spyOn($.fn, 'slider').andCallThrough();
|
||||
state = jasmine.initializePlayer();
|
||||
});
|
||||
});
|
||||
|
||||
it('changes ARIA attributes', function () {
|
||||
var sliderHandle = $('div.volume-slider>a.ui-slider-handle');
|
||||
expect(sliderHandle).toHaveAttrs({
|
||||
'aria-valuenow': data.value.toString(10),
|
||||
'aria-valuetext': data.expectation
|
||||
it('initialize currentVolume to 100%', function () {
|
||||
// Please note that:
|
||||
// 0% -> 0
|
||||
// 100% -> 1.0
|
||||
expect(state.videoVolumeControl.currentVolume).toEqual(1);
|
||||
});
|
||||
|
||||
it('render the volume control', function () {
|
||||
expect(state.videoControl.secondaryControlsEl.html())
|
||||
.toContain("<div class=\"volume\">\n");
|
||||
});
|
||||
|
||||
it('create the slider', function () {
|
||||
expect($.fn.slider).toHaveBeenCalledWith({
|
||||
orientation: "vertical",
|
||||
range: "min",
|
||||
min: 0,
|
||||
max: 100,
|
||||
value: state.videoVolumeControl.currentVolume,
|
||||
change: state.videoVolumeControl.onChange,
|
||||
slide: state.videoVolumeControl.onChange
|
||||
});
|
||||
});
|
||||
|
||||
it('add ARIA attributes to slider handle', function () {
|
||||
var sliderHandle = $('div.volume-slider>a.ui-slider-handle'),
|
||||
arr = [
|
||||
'muted', 'very low', 'low', 'average', 'loud',
|
||||
'very loud', 'maximum'
|
||||
];
|
||||
|
||||
expect(sliderHandle).toHaveAttrs({
|
||||
'role': 'slider',
|
||||
'title': 'volume',
|
||||
'aria-disabled': 'false',
|
||||
'aria-valuemin': '0',
|
||||
'aria-valuemax': '100'
|
||||
});
|
||||
expect(sliderHandle.attr('aria-valuenow')).toBeInRange(0, 100);
|
||||
expect(sliderHandle.attr('aria-valuetext')).toBeInArray(arr);
|
||||
});
|
||||
|
||||
it('add ARIA attributes to volume control', function () {
|
||||
var volumeControl = $('div.volume>a');
|
||||
|
||||
expect(volumeControl).toHaveAttrs({
|
||||
'role': 'button',
|
||||
'title': 'Volume',
|
||||
'aria-disabled': 'false'
|
||||
});
|
||||
});
|
||||
|
||||
it('bind the volume control', function () {
|
||||
expect($('.volume>a')).toHandleWith(
|
||||
'click', state.videoVolumeControl.toggleMute
|
||||
);
|
||||
expect($('.volume')).not.toHaveClass('open');
|
||||
|
||||
$('.volume').mouseenter();
|
||||
expect($('.volume')).toHaveClass('open');
|
||||
|
||||
$('.volume').mouseleave();
|
||||
expect($('.volume')).not.toHaveClass('open');
|
||||
});
|
||||
});
|
||||
|
||||
describe('onChange', function () {
|
||||
var initialData = [{
|
||||
range: 'muted',
|
||||
value: 0,
|
||||
expectation: 'muted'
|
||||
}, {
|
||||
range: 'in ]0,20]',
|
||||
value: 10,
|
||||
expectation: 'very low'
|
||||
}, {
|
||||
range: 'in ]20,40]',
|
||||
value: 30,
|
||||
expectation: 'low'
|
||||
}, {
|
||||
range: 'in ]40,60]',
|
||||
value: 50,
|
||||
expectation: 'average'
|
||||
}, {
|
||||
range: 'in ]60,80]',
|
||||
value: 70,
|
||||
expectation: 'loud'
|
||||
}, {
|
||||
range: 'in ]80,100[',
|
||||
value: 90,
|
||||
expectation: 'very loud'
|
||||
}, {
|
||||
range: 'maximum',
|
||||
value: 100,
|
||||
expectation: 'maximum'
|
||||
}];
|
||||
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
});
|
||||
|
||||
describe('when the new volume is more than 0', function () {
|
||||
beforeEach(function () {
|
||||
state.videoVolumeControl.onChange(void 0, {
|
||||
value: 60
|
||||
});
|
||||
});
|
||||
|
||||
it('set the player volume', function () {
|
||||
expect(state.videoVolumeControl.currentVolume).toEqual(60);
|
||||
});
|
||||
|
||||
it('remote muted class', function () {
|
||||
expect($('.volume')).not.toHaveClass('muted');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the new volume is 0', function () {
|
||||
beforeEach(function () {
|
||||
state.videoVolumeControl.onChange(void 0, {
|
||||
value: 0
|
||||
});
|
||||
});
|
||||
|
||||
it('set the player volume', function () {
|
||||
expect(state.videoVolumeControl.currentVolume).toEqual(0);
|
||||
});
|
||||
|
||||
it('add muted class', function () {
|
||||
expect($('.volume')).toHaveClass('muted');
|
||||
});
|
||||
});
|
||||
|
||||
$.each(initialData, function (index, data) {
|
||||
describe('when the new volume is ' + data.range, function () {
|
||||
beforeEach(function () {
|
||||
state.videoVolumeControl.onChange(void 0, {
|
||||
value: data.value
|
||||
});
|
||||
});
|
||||
|
||||
it('changes ARIA attributes', function () {
|
||||
var sliderHandle = $(
|
||||
'div.volume-slider>a.ui-slider-handle'
|
||||
);
|
||||
|
||||
expect(sliderHandle).toHaveAttrs({
|
||||
'aria-valuenow': data.value.toString(10),
|
||||
'aria-valuetext': data.expectation
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggleMute', function () {
|
||||
beforeEach(function () {
|
||||
state = jasmine.initializePlayer();
|
||||
});
|
||||
|
||||
describe('when the current volume is more than 0', function () {
|
||||
beforeEach(function () {
|
||||
state.videoVolumeControl.currentVolume = 60;
|
||||
state.videoVolumeControl.buttonEl.trigger('click');
|
||||
});
|
||||
|
||||
it('save the previous volume', function () {
|
||||
expect(state.videoVolumeControl.previousVolume).toEqual(60);
|
||||
});
|
||||
|
||||
it('set the player volume', function () {
|
||||
expect(state.videoVolumeControl.currentVolume).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the current volume is 0', function () {
|
||||
beforeEach(function () {
|
||||
state.videoVolumeControl.currentVolume = 0;
|
||||
state.videoVolumeControl.previousVolume = 60;
|
||||
state.videoVolumeControl.buttonEl.trigger('click');
|
||||
});
|
||||
|
||||
it('set the player volume to previous volume', function () {
|
||||
expect(state.videoVolumeControl.currentVolume).toEqual(60);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggleMute', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
});
|
||||
|
||||
describe('when the current volume is more than 0', function() {
|
||||
beforeEach(function() {
|
||||
videoVolumeControl.currentVolume = 60;
|
||||
videoVolumeControl.buttonEl.trigger('click');
|
||||
});
|
||||
|
||||
it('save the previous volume', function() {
|
||||
expect(videoVolumeControl.previousVolume).toEqual(60);
|
||||
});
|
||||
|
||||
it('set the player volume', function() {
|
||||
expect(videoVolumeControl.currentVolume).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the current volume is 0', function() {
|
||||
beforeEach(function() {
|
||||
videoVolumeControl.currentVolume = 0;
|
||||
videoVolumeControl.previousVolume = 60;
|
||||
videoVolumeControl.buttonEl.trigger('click');
|
||||
});
|
||||
|
||||
it('set the player volume to previous volume', function() {
|
||||
expect(videoVolumeControl.currentVolume).toEqual(60);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -559,16 +559,32 @@ function (VideoPlayer) {
|
||||
// example the length of the video can be determined from the meta
|
||||
// data.
|
||||
function fetchMetadata() {
|
||||
var _this = this;
|
||||
var _this = this,
|
||||
metadataXHRs = [];
|
||||
|
||||
this.metadata = {};
|
||||
|
||||
$.each(this.videos, function (speed, url) {
|
||||
_this.getVideoMetadata(url, function (data) {
|
||||
var xhr = _this.getVideoMetadata(url, function (data) {
|
||||
if (data.data) {
|
||||
_this.metadata[data.data.id] = data.data;
|
||||
}
|
||||
});
|
||||
|
||||
metadataXHRs.push(xhr);
|
||||
});
|
||||
|
||||
$.when.apply(this, metadataXHRs).done(function () {
|
||||
_this.el.trigger('metadata_received');
|
||||
|
||||
// Not only do we trigger the "metadata_received" event, we also
|
||||
// set a flag to notify that metadata has been received. This
|
||||
// allows for code that will miss the "metadata_received" event
|
||||
// to know that metadata has been received. This is important in
|
||||
// cases when some code will subscribe to the "metadata_received"
|
||||
// event after it has been triggered.
|
||||
_this.youtubeMetadataReceived = true;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -176,52 +176,21 @@ function (HTML5Video, Resizer) {
|
||||
|
||||
_resize(state, videoWidth, videoHeight);
|
||||
|
||||
// We wait for metadata to arrive, before we request the update
|
||||
// of the VCR video time, and of the start-end time region.
|
||||
// Metadata contains duration of the video. We wait for 2
|
||||
// seconds, and then abandon our attempts to update the VCR
|
||||
// video time (and the start-end time region) using metadata.
|
||||
(function () {
|
||||
var checkInterval = window.setInterval(
|
||||
checkForMetadata, 50
|
||||
),
|
||||
numberOfChecks = 0;
|
||||
|
||||
return;
|
||||
|
||||
function checkForMetadata() {
|
||||
if (state.metadata && state.metadata[state.youtubeId()]) {
|
||||
duration = state.videoPlayer.duration();
|
||||
|
||||
// After initialization, update the VCR with total time.
|
||||
// At this point only the metadata duration is available (not
|
||||
// very precise), but it is better than having 00:00:00 for
|
||||
// total time.
|
||||
state.trigger(
|
||||
'videoControl.updateVcrVidTime',
|
||||
{
|
||||
time: 0,
|
||||
duration: duration
|
||||
}
|
||||
);
|
||||
|
||||
state.trigger(
|
||||
'videoProgressSlider.updateStartEndTimeRegion',
|
||||
{
|
||||
duration: duration
|
||||
}
|
||||
);
|
||||
|
||||
window.clearInterval(checkInterval);
|
||||
} else {
|
||||
numberOfChecks += 1;
|
||||
|
||||
if (numberOfChecks === 40) {
|
||||
window.clearInterval(checkInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}());
|
||||
// After initialization, update the VCR with total time.
|
||||
// At this point only the metadata duration is available (not
|
||||
// very precise), but it is better than having 00:00:00 for
|
||||
// total time.
|
||||
if (state.youtubeMetadataReceived) {
|
||||
// Metadata was already received, and is available.
|
||||
_updateVcrAndRegion(state);
|
||||
} else {
|
||||
// We wait for metadata to arrive, before we request the update
|
||||
// of the VCR video time, and of the start-end time region.
|
||||
// Metadata contains duration of the video.
|
||||
state.el.on('metadata_received', function () {
|
||||
_updateVcrAndRegion(state);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -230,7 +199,26 @@ function (HTML5Video, Resizer) {
|
||||
}
|
||||
}
|
||||
|
||||
function _resize (state, videoWidth, videoHeight) {
|
||||
function _updateVcrAndRegion(state) {
|
||||
var duration = state.videoPlayer.duration();
|
||||
|
||||
state.trigger(
|
||||
'videoControl.updateVcrVidTime',
|
||||
{
|
||||
time: 0,
|
||||
duration: duration
|
||||
}
|
||||
);
|
||||
|
||||
state.trigger(
|
||||
'videoProgressSlider.updateStartEndTimeRegion',
|
||||
{
|
||||
duration: duration
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function _resize(state, videoWidth, videoHeight) {
|
||||
state.resizer = new Resizer({
|
||||
element: state.videoEl,
|
||||
elementRatio: videoWidth/videoHeight,
|
||||
@@ -783,7 +771,17 @@ function (HTML5Video, Resizer) {
|
||||
* This instability is internal to the player API (or browser internals).
|
||||
*/
|
||||
function duration() {
|
||||
var dur = this.videoPlayer.player.getDuration();
|
||||
var dur;
|
||||
|
||||
// Sometimes the YouTube API doesn't finish instantiating all of it's
|
||||
// methods, but the execution point arrives here.
|
||||
//
|
||||
// This happens when you have start and end times set, and click "Edit"
|
||||
// in Studio, and then "Save". The Video editor dialog closes, the
|
||||
// video reloads, but the start-end range is not visible.
|
||||
if (this.videoPlayer.player.getDuration) {
|
||||
dur = this.videoPlayer.player.getDuration();
|
||||
}
|
||||
|
||||
// For YouTube videos, before the video starts playing, the API
|
||||
// function player.getDuration() will return 0. This means that the VCR
|
||||
|
||||
Reference in New Issue
Block a user