Commit af56a2df by polesye

BLD-518: Fix video volume cookie.

parent 76f4eaf9
...@@ -335,21 +335,23 @@ ...@@ -335,21 +335,23 @@
beforeEach(function () { beforeEach(function () {
initialize(); initialize();
spyOn(videoPlayer, 'updatePlayTime'); runs(function () {
spyOn(videoPlayer, 'log');
spyOn(videoPlayer.player, 'seekTo');
state.videoPlayer.play(); state.videoPlayer.play();
});
waitsFor(function () { waitsFor(function () {
return videoPlayer.isPlaying(); duration = videoPlayer.duration();
return duration > 0 && videoPlayer.isPlaying();
}, 'video begins playing', WAIT_TIMEOUT); }, 'video begins playing', WAIT_TIMEOUT);
}); });
it('Slider event causes log update', function () { it('Slider event causes log update', function () {
runs(function () { runs(function () {
var currentTime = videoPlayer.currentTime; var currentTime = videoPlayer.currentTime;
spyOn(videoPlayer, 'log');
videoProgressSlider.onSlide( videoProgressSlider.onSlide(
jQuery.Event('slide'), { value: 2 } jQuery.Event('slide'), { value: 2 }
); );
...@@ -367,6 +369,7 @@ ...@@ -367,6 +369,7 @@
it('seek the player', function () { it('seek the player', function () {
runs(function () { runs(function () {
spyOn(videoPlayer.player, 'seekTo');
videoProgressSlider.onSlide( videoProgressSlider.onSlide(
jQuery.Event('slide'), { value: 60 } jQuery.Event('slide'), { value: 60 }
); );
...@@ -378,6 +381,7 @@ ...@@ -378,6 +381,7 @@
it('call updatePlayTime on player', function () { it('call updatePlayTime on player', function () {
runs(function () { runs(function () {
spyOn(videoPlayer, 'updatePlayTime');
videoProgressSlider.onSlide( videoProgressSlider.onSlide(
jQuery.Event('slide'), { value: 60 } jQuery.Event('slide'), { value: 60 }
); );
...@@ -476,19 +480,38 @@ ...@@ -476,19 +480,38 @@
videoPlayer.onPlay(); videoPlayer.onPlay();
expect(videoPlayer.onSpeedChange.calls.length).toEqual(1); expect(videoPlayer.onSpeedChange.calls.length).toEqual(1);
}); });
it('video has a correct volume', function () {
spyOn(videoPlayer.player, 'setVolume');
state.currentVolume = '0.26';
videoPlayer.onPlay();
expect(videoPlayer.player.setVolume).toHaveBeenCalledWith('0.26');
});
}); });
}); });
describe('onVolumeChange', function () { describe('onVolumeChange', function () {
beforeEach(function () { beforeEach(function () {
initialize(); initialize();
});
it('set the volume on player', function () {
spyOn(videoPlayer.player, 'setVolume'); spyOn(videoPlayer.player, 'setVolume');
videoPlayer.onVolumeChange(60); videoPlayer.onVolumeChange(60);
expect(videoPlayer.player.setVolume).toHaveBeenCalledWith(60);
}); });
it('set the volume on player', function () { describe('when the video is not playing', function () {
expect(videoPlayer.player.setVolume).toHaveBeenCalledWith(60); beforeEach(function () {
videoPlayer.player.setVolume('1');
});
it('video has a correct volume', function () {
spyOn(videoPlayer.player, 'setVolume');
state.currentVolume = '0.26';
videoPlayer.onPlay();
expect(videoPlayer.player.setVolume).toHaveBeenCalledWith('0.26');
});
}); });
}); });
...@@ -922,7 +945,9 @@ ...@@ -922,7 +945,9 @@
}); });
waitsFor(function () { waitsFor(function () {
return videoPlayer.isPlaying(); duration = videoPlayer.duration();
return duration > 0 && videoPlayer.isPlaying();
},'Video does not play.' , WAIT_TIMEOUT); },'Video does not play.' , WAIT_TIMEOUT);
runs(function () { runs(function () {
......
...@@ -323,6 +323,7 @@ function (VideoPlayer) { ...@@ -323,6 +323,7 @@ function (VideoPlayer) {
// element has a CSS class 'fullscreen'. // element has a CSS class 'fullscreen'.
this.__dfd__ = $.Deferred(); this.__dfd__ = $.Deferred();
this.isFullScreen = false; this.isFullScreen = false;
this.currentVolume = 100;
this.isTouch = onTouchBasedDevice() || ''; this.isTouch = onTouchBasedDevice() || '';
// The parent element of the video, and the ID. // The parent element of the video, and the ID.
......
...@@ -193,6 +193,9 @@ function () { ...@@ -193,6 +193,9 @@ function () {
sourceStr[videoType] = sourceStr[videoType] =
'<source ' + '<source ' +
'src="' + _this.config.videoSources[videoType] + 'src="' + _this.config.videoSources[videoType] +
// Following hack allows to open the same video twice
// https://code.google.com/p/chromium/issues/detail?id=31014
'?' + (new Date()).getTime() +
'" ' + 'type="video/' + videoType + '" ' + '" ' + 'type="video/' + videoType + '" ' +
'/> '; '/> ';
} }
......
...@@ -70,6 +70,7 @@ function (HTML5Video, Resizer) { ...@@ -70,6 +70,7 @@ function (HTML5Video, Resizer) {
if (state.currentPlayerMode !== 'flash') { if (state.currentPlayerMode !== 'flash') {
state.videoPlayer.onSpeedChange(state.speed); state.videoPlayer.onSpeedChange(state.speed);
} }
state.videoPlayer.player.setVolume(state.currentVolume);
}); });
if (state.videoType === 'youtube') { if (state.videoType === 'youtube') {
......
...@@ -50,59 +50,68 @@ function () { ...@@ -50,59 +50,68 @@ function () {
// make the created DOM elements available via the 'state' object. Much easier to work this // make the created DOM elements available via the 'state' object. Much easier to work this
// way - you don't have to do repeated jQuery element selects. // way - you don't have to do repeated jQuery element selects.
function _renderElements(state) { function _renderElements(state) {
state.videoVolumeControl.el = state.el.find('div.volume'); var volumeControl = state.videoVolumeControl,
element = state.el.find('div.volume'),
state.videoVolumeControl.buttonEl = state.videoVolumeControl.el.find('a'); button = element.find('a'),
state.videoVolumeControl.volumeSliderEl = state.videoVolumeControl.el.find('.volume-slider'); volumeSlider = element.find('.volume-slider'),
// Figure out what the current volume is. If no information about
// volume level could be retrieved, then we will use the default 100
// level (full volume).
currentVolume = parseInt($.cookie('video_player_volume_level'), 10),
// Set it up so that muting/unmuting works correctly.
previousVolume = 100,
slider, buttonStr, volumeSliderHandleEl;
state.videoControl.secondaryControlsEl.prepend(state.videoVolumeControl.el); state.videoControl.secondaryControlsEl.prepend(element);
// Figure out what the current volume is. If no information about volume level could be retrieved, if (!isFinite(currentVolume)) {
// then we will use the default 100 level (full volume). currentVolume = 100;
state.videoVolumeControl.currentVolume = parseInt($.cookie('video_player_volume_level'), 10);
if (!isFinite(state.videoVolumeControl.currentVolume)) {
state.videoVolumeControl.currentVolume = 100;
} }
// Set it up so that muting/unmuting works correctly. slider = volumeSlider.slider({
state.videoVolumeControl.previousVolume = 100;
state.videoVolumeControl.slider = state.videoVolumeControl.volumeSliderEl.slider({
orientation: 'vertical', orientation: 'vertical',
range: 'min', range: 'min',
min: 0, min: 0,
max: 100, max: 100,
value: state.videoVolumeControl.currentVolume, value: currentVolume,
change: state.videoVolumeControl.onChange, change: volumeControl.onChange,
slide: state.videoVolumeControl.onChange slide: volumeControl.onChange
}); });
state.videoVolumeControl.el.toggleClass('muted', state.videoVolumeControl.currentVolume === 0); element.toggleClass('muted', currentVolume === 0);
// ARIA // ARIA
// Let screen readers know that: // Let screen readers know that:
// This anchor behaves as a button named 'Volume'. // This anchor behaves as a button named 'Volume'.
var currentVolume = state.videoVolumeControl.currentVolume,
buttonStr = (currentVolume === 0) ? 'Volume muted' : 'Volume'; buttonStr = (currentVolume === 0) ? 'Volume muted' : 'Volume';
// We add the aria-label attribute because the title attribute cannot be // We add the aria-label attribute because the title attribute cannot be
// read. // read.
state.videoVolumeControl.buttonEl.attr('aria-label', gettext(buttonStr)); button.attr('aria-label', gettext(buttonStr));
// Let screen readers know that this anchor, representing the slider // Let screen readers know that this anchor, representing the slider
// handle, behaves as a slider named 'volume'. // handle, behaves as a slider named 'volume'.
var volumeSlider = state.videoVolumeControl.slider; volumeSliderHandleEl = slider.find('.ui-slider-handle');
state.videoVolumeControl.volumeSliderHandleEl = state.videoVolumeControl
.volumeSliderEl volumeSliderHandleEl.attr({
.find('.ui-slider-handle');
state.videoVolumeControl.volumeSliderHandleEl.attr({
'role': 'slider', 'role': 'slider',
'title': 'volume', 'title': 'volume',
'aria-disabled': false, 'aria-disabled': false,
'aria-valuemin': volumeSlider.slider('option', 'min'), 'aria-valuemin': slider.slider('option', 'min'),
'aria-valuemax': volumeSlider.slider('option', 'max'), 'aria-valuemax': slider.slider('option', 'max'),
'aria-valuenow': volumeSlider.slider('option', 'value'), 'aria-valuenow': slider.slider('option', 'value'),
'aria-valuetext': getVolumeDescription(volumeSlider.slider('option', 'value')) 'aria-valuetext': getVolumeDescription(slider.slider('option', 'value'))
});
state.currentVolume = currentVolume;
$.extend(state.videoVolumeControl, {
el: element,
buttonEl: button,
volumeSliderEl: volumeSlider,
currentVolume: currentVolume,
previousVolume: previousVolume,
slider: slider,
volumeSliderHandleEl: volumeSliderHandleEl
}); });
} }
......
#pylint: disable=C0111 #pylint: disable=C0111
from lettuce import world, step from lettuce import world, step
from lettuce.django import django_url
from common import i_am_registered_for_the_course, section_location, visit_scenario_item from common import i_am_registered_for_the_course, section_location, visit_scenario_item
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
...@@ -94,8 +93,10 @@ def video_is_rendered(_step, mode): ...@@ -94,8 +93,10 @@ def video_is_rendered(_step, mode):
@step('all sources are correct$') @step('all sources are correct$')
def all_sources_are_correct(_step): def all_sources_are_correct(_step):
sources = world.css_find('.video video source') elements = world.css_find('.video video source')
assert set(source['src'] for source in sources) == set(HTML5_SOURCES) sources = [source['src'].split('?')[0] for source in elements]
assert set(sources) == set(HTML5_SOURCES)
@step('error message is shown$') @step('error message is shown$')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment