Commit 6035d0a2 by Peter Fogg

Addresses latest comments on pull request #132. In particular:

- Make 1.0x speed default Youtube ID Lyla's introduction video.
- Add acceptance tests for toggling captions on/off.
- Move captions settings acceptance tests into video-editor.feature.
- Rename acceptance test methods to reflect their function.
- Remove undefined variable from video Jasmine tests.
- Test VideoDescriptor.from_xml when no attributes are set.
- Convert Stringy* to non-Stringy equivalents.
- Test parsing of Youtube ID strings and times in more cases.
- Remove some commented-out code.
parent 206f5825
......@@ -11,3 +11,13 @@ Feature: Video Component Editor
And I edit and select Settings
Then I can modify the display name
And my display name change is persisted on save
Scenario: Captions are hidden when "show captions" is false
Given I have created a Video component
And I have set "show captions" to False
Then when I view the video it does not show the captions
Scenario: Captions are shown when "show captions" is true
Given I have created a Video component
And I have set "show captions" to True
Then when I view the video it does show the captions
......@@ -16,15 +16,9 @@ Feature: Video Component
Scenario: Captions are shown correctly
Given I have created a Video component
And I have shown captions
Then when I view the video it does show the captions
Scenario: Captions are hidden when "show captions" is false
Scenario: Captions are toggled correctly
Given I have created a Video component
And I have set "show captions" to False
Then when I view the video it does not show the captions
Scenario: Captions are shown when "show captions" is true
Given I have created a Video component
And I have set "show captions" to True
And I have toggled captions
Then when I view the video it does show the captions
......@@ -18,31 +18,33 @@ def video_takes_a_single_click(step):
assert(world.is_css_present('.xmodule_VideoModule'))
@step('I have (hidden|shown) captions')
@step('I have (hidden|toggled) captions')
def hide_or_show_captions(step, shown):
button_css = 'a.hide-subtitles'
if shown == 'hidden':
world.css_click('a.hide-subtitles')
world.css_click(button_css)
if shown == 'toggled':
world.css_click(button_css)
# When we click the first time, a tooltip shows up. We want to
# click the button rather than the tooltip, so move the mouse
# away to make it disappear.
button = world.css_find(button_css)
button.mouse_out()
world.css_click(button_css)
@step('when I view the video it (.*) show the captions')
def does_not_show_captions(step, show_captions):
def shows_captions(step, show_captions):
# Prevent cookies from overriding course settings
world.browser.cookies.delete('hide_captions')
if show_captions == 'does not':
assert world.css_find('.video')[0].has_class('closed')
else:
assert not world.css_find('.video')[0].has_class('closed')
# @step('when I view the video it does show the captions')
# def shows_captions(step):
# # Prevent cookies from overriding course settings
# world.browser.cookies.delete('hide_captions')
# assert not world.css_find('.video')[0].has_class('closed')
assert world.is_css_not_present('.video.closed')
@step('I have set "show captions" to (.*)')
def set_show_captions_false(step, setting):
def set_show_captions(step, setting):
world.css_click('a.edit-button')
world.browser.select('Show Captions', setting)
world.css_click('a.save-button')
......@@ -59,7 +59,7 @@ describe 'Video', ->
@originalYT = window.YT
window.YT = { Player: true }
spyOn(window, 'VideoPlayer').andReturn(@stubVideoPlayer)
@video = new Video '#example', @videosDefinition
@video = new Video '#example'
afterEach ->
window.YT = @originalYT
......@@ -72,7 +72,7 @@ describe 'Video', ->
beforeEach ->
@originalYT = window.YT
window.YT = {}
@video = new Video '#example', @videosDefinition
@video = new Video '#example'
afterEach ->
window.YT = @originalYT
......@@ -85,7 +85,7 @@ describe 'Video', ->
@originalYT = window.YT
window.YT = {}
spyOn(window, 'VideoPlayer').andReturn(@stubVideoPlayer)
@video = new Video '#example', @videosDefinition
@video = new Video '#example'
window.onYouTubePlayerAPIReady()
afterEach ->
......@@ -98,7 +98,7 @@ describe 'Video', ->
describe 'youtubeId', ->
beforeEach ->
$.cookie.andReturn '1.0'
@video = new Video '#example', @videosDefinition
@video = new Video '#example'
describe 'with speed', ->
it 'return the video id for given speed', ->
......@@ -111,7 +111,7 @@ describe 'Video', ->
describe 'setSpeed', ->
beforeEach ->
@video = new Video '#example', @videosDefinition
@video = new Video '#example'
describe 'when new speed is available', ->
beforeEach ->
......@@ -132,14 +132,14 @@ describe 'Video', ->
describe 'getDuration', ->
beforeEach ->
@video = new Video '#example', @videosDefinition
@video = new Video '#example'
it 'return duration for current video', ->
expect(@video.getDuration()).toEqual 200
describe 'log', ->
beforeEach ->
@video = new Video '#example', @videosDefinition
@video = new Video '#example'
@video.setSpeed '1.0'
spyOn Logger, 'log'
@video.player = { currentTime: 25 }
......
......@@ -57,3 +57,20 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
self.assertEquals(output.end_time, 0.0)
self.assertEquals(output.track, 'http://www.example.com/track')
self.assertEquals(output.source, 'http://www.example.com/source.mp4')
def test_from_xml_no_attributes(self):
'''
Make sure settings are correct if none are explicitly set in XML.
'''
module_system = DummySystem(load_error_modules=True)
xml_data = '<video></video>'
output = VideoDescriptor.from_xml(xml_data, module_system)
self.assertEquals(output.youtube_id_0_75, '')
self.assertEquals(output.youtube_id_1_0, 'OEoXaMPEzfM')
self.assertEquals(output.youtube_id_1_25, '')
self.assertEquals(output.youtube_id_1_5, '')
self.assertEquals(output.show_captions, True)
self.assertEquals(output.start_time, 0.0)
self.assertEquals(output.end_time, 0.0)
self.assertEquals(output.track, '')
self.assertEquals(output.source, '')
......@@ -14,8 +14,7 @@ from django.http import Http404
from xmodule.x_module import XModule
from xmodule.raw_module import RawDescriptor
from xmodule.editing_module import MetadataOnlyEditingDescriptor
from xblock.core import Integer, Scope, String
from fields import StringyFloat, StringyBoolean
from xblock.core import Integer, Scope, String, Float, Boolean
log = logging.getLogger(__name__)
......@@ -23,13 +22,13 @@ log = logging.getLogger(__name__)
class VideoFields(object):
"""Fields for `VideoModule` and `VideoDescriptor`."""
position = Integer(help="Current position in the video", scope=Scope.user_state, default=0)
show_captions = StringyBoolean(help="This controls whether or not captions are shown by default.", display_name="Show Captions", scope=Scope.settings, default=True)
youtube_id_1_0 = String(help="This is the Youtube ID reference for the normal speed video.", display_name="Default Speed", scope=Scope.settings, default="")
show_captions = Boolean(help="This controls whether or not captions are shown by default.", display_name="Show Captions", scope=Scope.settings, default=True)
youtube_id_1_0 = String(help="This is the Youtube ID reference for the normal speed video.", display_name="Default Speed", scope=Scope.settings, default="OEoXaMPEzfM")
youtube_id_0_75 = String(help="The Youtube ID for the .75x speed video.", display_name="Speed: .75x", scope=Scope.settings, default="")
youtube_id_1_25 = String(help="The Youtube ID for the 1.25x speed video.", display_name="Speed: 1.25x", scope=Scope.settings, default="")
youtube_id_1_5 = String(help="The Youtube ID for the 1.5x speed video.", display_name="Speed: 1.5x", scope=Scope.settings, default="")
start_time = StringyFloat(help="Time the video starts", display_name="Start Time", scope=Scope.settings, default=0.0)
end_time = StringyFloat(help="Time the video ends", display_name="End Time", scope=Scope.settings, default=0.0)
start_time = Float(help="Time the video starts", display_name="Start Time", scope=Scope.settings, default=0.0)
end_time = Float(help="Time the video ends", display_name="End Time", scope=Scope.settings, default=0.0)
source = String(help="The external URL to download the video. This appears as a link beneath the video.", display_name="Download Video", scope=Scope.settings, default="")
track = String(help="The external URL to download the subtitle track. This appears as a link beneath the video.", display_name="Download Track", scope=Scope.settings, default="")
......@@ -125,7 +124,9 @@ class VideoDescriptor(VideoFields,
video.youtube_id_1_25 = speeds['1.25']
if speeds['1.50']:
video.youtube_id_1_5 = speeds['1.50']
video.show_captions = True if xml.get('show_captions') == 'true' else False
show_captions = xml.get('show_captions')
if show_captions:
video.show_captions = json.loads(show_captions)
source = _get_first_external(xml, 'source')
if source:
video.source = source
......@@ -177,7 +178,7 @@ def _parse_youtube(data):
def _parse_time(str_time):
"""Converts s in '12:34:45' format to seconds. If s is
None, returns empty string"""
if str_time is None:
if str_time is None or str_time == '':
return ''
else:
obj_time = time.strptime(str_time, '%H:%M:%S')
......
......@@ -68,13 +68,23 @@ class VideoModuleLogicTest(LogicTest):
}
def test_parse_time(self):
"""Ensure that times are parse correctly into seconds."""
"""Ensure that times are parsed correctly into seconds."""
output = _parse_time('00:04:07')
self.assertEqual(output, 247)
def test_parse_time_none(self):
"""Check parsing of None."""
output = _parse_time(None)
self.assertEqual(output, '')
def test_parse_time_empty(self):
"""Check parsing of the empty string."""
output = _parse_time('')
self.assertEqual(output, '')
def test_parse_youtube(self):
"""Test parsing old-style Youtube ID strings into a dict."""
youtube_str = '0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg'
youtube_str = '0.75:jNCf2gIqpeE,1.00:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg'
output = _parse_youtube(youtube_str)
self.assertEqual(output, {'0.75': 'jNCf2gIqpeE',
'1.00': 'ZwkTiUPN0mg',
......@@ -92,3 +102,11 @@ class VideoModuleLogicTest(LogicTest):
'1.00': '',
'1.25': '',
'1.50': ''})
def test_parse_youtube_key_format(self):
"""
Make sure that inconsistent speed keys are parsed correctly.
"""
youtube_str = '1.00:p2Q6BrNhdh8'
youtube_str_hack = '1.0:p2Q6BrNhdh8'
self.assertEqual(_parse_youtube(youtube_str), _parse_youtube(youtube_str_hack))
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