Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
de1c6879
Commit
de1c6879
authored
Jun 06, 2013
by
dcadams
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of github.com:edx/edx-platform into feature-dcadams-usermanagement
parents
bc5d7923
74338450
Show whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
601 additions
and
236 deletions
+601
-236
cms/djangoapps/contentstore/tests/test_utils.py
+24
-0
cms/djangoapps/contentstore/utils.py
+18
-3
cms/envs/aws.py
+1
-0
cms/envs/common.py
+11
-0
common/djangoapps/mitxmako/tests.py
+4
-2
common/lib/xmodule/xmodule/js/fixtures/video.html
+12
-2
common/lib/xmodule/xmodule/js/spec/helper.coffee
+3
-7
common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee
+67
-44
common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee
+20
-27
common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee
+35
-20
common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee
+58
-50
common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee
+13
-13
common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee
+1
-2
common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee
+26
-22
common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee
+1
-1
common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee
+1
-1
common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee
+1
-1
common/lib/xmodule/xmodule/video_module.py
+28
-35
lms/djangoapps/courseware/tests/__init__.py
+108
-0
lms/djangoapps/courseware/tests/test_video_mongo.py
+27
-0
lms/djangoapps/courseware/tests/test_video_xml.py
+135
-0
lms/static/sass/base/_variables.scss
+2
-1
lms/static/sass/course/base/_base.scss
+2
-2
lms/static/sass/multicourse/_account.scss
+3
-3
No files found.
cms/djangoapps/contentstore/tests/test_utils.py
View file @
de1c6879
...
...
@@ -24,6 +24,30 @@ class LMSLinksTestCase(TestCase):
with
mock
.
patch
.
dict
(
'django.conf.settings.MITX_FEATURES'
,
{
'ENABLE_MKTG_SITE'
:
False
}):
self
.
assertEquals
(
self
.
get_about_page_link
(),
"//localhost:8000/courses/mitX/101/test/about"
)
@override_settings
(
MKTG_URLS
=
{
'ROOT'
:
'http://www.dummy'
})
def
about_page_marketing_site_remove_http_test
(
self
):
""" Get URL for about page, marketing root present, remove http://. """
with
mock
.
patch
.
dict
(
'django.conf.settings.MITX_FEATURES'
,
{
'ENABLE_MKTG_SITE'
:
True
}):
self
.
assertEquals
(
self
.
get_about_page_link
(),
"//www.dummy/courses/mitX/101/test/about"
)
@override_settings
(
MKTG_URLS
=
{
'ROOT'
:
'https://www.dummy'
})
def
about_page_marketing_site_remove_https_test
(
self
):
""" Get URL for about page, marketing root present, remove https://. """
with
mock
.
patch
.
dict
(
'django.conf.settings.MITX_FEATURES'
,
{
'ENABLE_MKTG_SITE'
:
True
}):
self
.
assertEquals
(
self
.
get_about_page_link
(),
"//www.dummy/courses/mitX/101/test/about"
)
@override_settings
(
MKTG_URLS
=
{
'ROOT'
:
'www.dummyhttps://x'
})
def
about_page_marketing_site_https__edge_test
(
self
):
""" Get URL for about page, only remove https:// at the beginning of the string. """
with
mock
.
patch
.
dict
(
'django.conf.settings.MITX_FEATURES'
,
{
'ENABLE_MKTG_SITE'
:
True
}):
self
.
assertEquals
(
self
.
get_about_page_link
(),
"//www.dummyhttps://x/courses/mitX/101/test/about"
)
@override_settings
(
MKTG_URLS
=
{})
def
about_page_marketing_urls_not_set_test
(
self
):
""" Error case. ENABLE_MKTG_SITE is True, but there is either no MKTG_URLS, or no MKTG_URLS Root property. """
with
mock
.
patch
.
dict
(
'django.conf.settings.MITX_FEATURES'
,
{
'ENABLE_MKTG_SITE'
:
True
}):
self
.
assertEquals
(
self
.
get_about_page_link
(),
None
)
@override_settings
(
LMS_BASE
=
None
)
def
about_page_no_lms_base_test
(
self
):
""" No LMS_BASE, nor is ENABLE_MKTG_SITE True """
...
...
cms/djangoapps/contentstore/utils.py
View file @
de1c6879
...
...
@@ -4,6 +4,10 @@ from xmodule.modulestore.django import modulestore
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
django.core.urlresolvers
import
reverse
import
copy
import
logging
import
re
log
=
logging
.
getLogger
(
__name__
)
DIRECT_ONLY_CATEGORIES
=
[
'course'
,
'chapter'
,
'sequential'
,
'about'
,
'static_tab'
,
'course_info'
]
...
...
@@ -108,9 +112,20 @@ def get_lms_link_for_about_page(location):
Returns the url to the course about page from the location tuple.
"""
if
settings
.
MITX_FEATURES
.
get
(
'ENABLE_MKTG_SITE'
,
False
):
# Root will be "www.edx.org". The complete URL will still not be exactly correct,
# but redirects exist from www.edx.org to get to the drupal course about page URL.
about_base
=
settings
.
MKTG_URLS
.
get
(
'ROOT'
)
if
not
hasattr
(
settings
,
'MKTG_URLS'
):
log
.
exception
(
"ENABLE_MKTG_SITE is True, but MKTG_URLS is not defined."
)
about_base
=
None
else
:
marketing_urls
=
settings
.
MKTG_URLS
if
marketing_urls
.
get
(
'ROOT'
,
None
)
is
None
:
log
.
exception
(
'There is no ROOT defined in MKTG_URLS'
)
about_base
=
None
else
:
# Root will be "https://www.edx.org". The complete URL will still not be exactly correct,
# but redirects exist from www.edx.org to get to the Drupal course about page URL.
about_base
=
marketing_urls
.
get
(
'ROOT'
)
# Strip off https:// (or http://) to be consistent with the formatting of LMS_BASE.
about_base
=
re
.
sub
(
r"^https?://"
,
""
,
about_base
)
elif
settings
.
LMS_BASE
is
not
None
:
about_base
=
settings
.
LMS_BASE
else
:
...
...
cms/envs/aws.py
View file @
de1c6879
...
...
@@ -103,6 +103,7 @@ DEFAULT_FROM_EMAIL = ENV_TOKENS.get('DEFAULT_FROM_EMAIL', DEFAULT_FROM_EMAIL)
DEFAULT_FEEDBACK_EMAIL
=
ENV_TOKENS
.
get
(
'DEFAULT_FEEDBACK_EMAIL'
,
DEFAULT_FEEDBACK_EMAIL
)
ADMINS
=
ENV_TOKENS
.
get
(
'ADMINS'
,
ADMINS
)
SERVER_EMAIL
=
ENV_TOKENS
.
get
(
'SERVER_EMAIL'
,
SERVER_EMAIL
)
MKTG_URLS
=
ENV_TOKENS
.
get
(
'MKTG_URLS'
,
MKTG_URLS
)
#Timezone overrides
TIME_ZONE
=
ENV_TOKENS
.
get
(
'TIME_ZONE'
,
TIME_ZONE
)
...
...
cms/envs/common.py
View file @
de1c6879
...
...
@@ -335,3 +335,14 @@ INSTALLED_APPS = (
################# EDX MARKETING SITE ##################################
EDXMKTG_COOKIE_NAME
=
'edxloggedin'
MKTG_URLS
=
{}
MKTG_URL_LINK_MAP
=
{
'ABOUT'
:
'about_edx'
,
'CONTACT'
:
'contact'
,
'FAQ'
:
'help_edx'
,
'COURSES'
:
'courses'
,
'ROOT'
:
'root'
,
'TOS'
:
'tos'
,
'HONOR'
:
'honor'
,
'PRIVACY'
:
'privacy_edx'
,
}
common/djangoapps/mitxmako/tests.py
View file @
de1c6879
...
...
@@ -4,13 +4,15 @@ from django.core.urlresolvers import reverse
from
django.conf
import
settings
from
mitxmako.shortcuts
import
marketing_link
from
mock
import
patch
from
nose.plugins.skip
import
SkipTest
class
ShortcutsTests
(
TestCase
):
"""
Test the mitxmako shortcuts file
"""
# TODO: fix this test. It is causing intermittent test failures on
# subsequent tests due to the way urls are loaded
raise
SkipTest
()
@override_settings
(
MKTG_URLS
=
{
'ROOT'
:
'dummy-root'
,
'ABOUT'
:
'/about-us'
})
@override_settings
(
MKTG_URL_LINK_MAP
=
{
'ABOUT'
:
'login'
})
def
test_marketing_link
(
self
):
...
...
common/lib/xmodule/xmodule/js/fixtures/video.html
View file @
de1c6879
<div
class=
"course-content"
>
<div
id=
"video_example"
class=
"video"
>
<div
id=
"video_example"
>
<div
id=
"example"
>
<div
id=
"video_id"
class=
"video"
data-streams=
"0.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId"
data-show-captions=
"true"
data-start=
""
data-end=
""
data-caption-asset-path=
"/static/subs/"
>
<div
class=
"tc-wrapper"
>
<article
class=
"video-wrapper"
>
<section
class=
"video-player"
>
<div
id=
"example
"
></div>
<div
id=
"id
"
></div>
</section>
<section
class=
"video-controls"
></section>
</article>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
common/lib/xmodule/xmodule/js/spec/helper.coffee
View file @
de1c6879
...
...
@@ -28,7 +28,7 @@ jasmine.stubRequests = ->
spyOn
(
$
,
'ajax'
).
andCallFake
(
settings
)
->
if
match
=
settings
.
url
.
match
/youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/
settings
.
success
data
:
jasmine
.
stubbedMetadata
[
match
[
1
]]
else
if
match
=
settings
.
url
.
match
/static\/subs\/(.+)\.srt\.sjson/
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'
)
...
...
@@ -47,19 +47,15 @@ jasmine.stubYoutubePlayer = ->
jasmine
.
stubVideoPlayer
=
(
context
,
enableParts
,
createPlayer
=
true
)
->
enableParts
=
[
enableParts
]
unless
$
.
isArray
(
enableParts
)
suite
=
context
.
suite
currentPartName
=
suite
.
description
while
suite
=
suite
.
parentSuite
enableParts
.
push
currentPartName
for
part
in
[
'VideoCaption'
,
'VideoSpeedControl'
,
'VideoVolumeControl'
,
'VideoProgressSlider'
]
unless
$
.
inArray
(
part
,
enableParts
)
>=
0
spyOn
window
,
part
loadFixtures
'video.html'
jasmine
.
stubRequests
()
YT
.
Player
=
undefined
context
.
video
=
new
Video
'example'
,
'.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId'
videosDefinition
=
'0.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId'
context
.
video
=
new
Video
'#example'
,
videosDefinition
jasmine
.
stubYoutubePlayer
()
if
createPlayer
return
new
VideoPlayer
(
video
:
context
.
video
)
...
...
common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee
View file @
de1c6879
# TODO: figure out why failing
xdescribe
'VideoCaption'
,
->
describe
'VideoCaption'
,
->
beforeEach
->
jasmine
.
stubVideoPlayer
@
$
(
'.subtitles'
).
remove
()
spyOn
(
VideoCaption
.
prototype
,
'fetchCaption'
).
andCallThrough
()
spyOn
(
$
,
'ajaxWithPrefix'
).
andCallThrough
()
window
.
onTouchBasedDevice
=
jasmine
.
createSpy
(
'onTouchBasedDevice'
).
andReturn
false
afterEach
->
YT
.
Player
=
undefined
$
.
fn
.
scrollTo
.
reset
()
$
(
'.subtitles'
).
remove
()
describe
'constructor'
,
->
beforeEach
->
spyOn
(
$
,
'getWithPrefix'
).
andCallThrough
()
describe
'always'
,
->
beforeEach
->
@
caption
=
new
VideoCaption
el
:
$
(
'.video'
),
youtubeId
:
'def456'
,
currentSpeed
:
'1.0'
@
player
=
jasmine
.
stubVideoPlayer
@
@
caption
=
@
player
.
caption
it
'set the youtube id'
,
->
expect
(
@
caption
.
youtubeId
).
toEqual
'
def456
'
expect
(
@
caption
.
youtubeId
).
toEqual
'
normalSpeedYoutubeId
'
it
'create the caption element'
,
->
expect
(
$
(
'.video'
)).
toContain
'ol.subtitles'
...
...
@@ -26,7 +28,12 @@ xdescribe 'VideoCaption', ->
expect
(
$
(
'.video'
)).
toContain
'a.hide-subtitles'
it
'fetch the caption'
,
->
expect
(
$
.
getWithPrefix
).
toHaveBeenCalledWith
@
caption
.
captionURL
(),
jasmine
.
any
(
Function
)
expect
(
@
caption
.
loaded
).
toBeTruthy
()
expect
(
@
caption
.
fetchCaption
).
toHaveBeenCalled
()
expect
(
$
.
ajaxWithPrefix
).
toHaveBeenCalledWith
url
:
@
caption
.
captionURL
()
notifyOnError
:
false
success
:
jasmine
.
any
(
Function
)
it
'bind window resize event'
,
->
expect
(
$
(
window
)).
toHandleWith
'resize'
,
@
caption
.
resize
...
...
@@ -42,17 +49,17 @@ xdescribe 'VideoCaption', ->
expect
(
$
(
'.subtitles'
)).
toHandleWith
'DOMMouseScroll'
,
@
caption
.
onMovement
describe
'when on a non touch-based device'
,
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
false
@
caption
=
new
VideoCaption
el
:
$
(
'.video'
),
youtubeId
:
'def456'
,
currentSpeed
:
'1.0'
@
player
=
jasmine
.
stubVideoPlayer
@
@
caption
=
@
player
.
caption
it
'render the caption'
,
->
expect
(
$
(
'.subtitles'
).
html
()).
toMatch
new
RegExp
(
'''
<li data-index="0" data-start="0">Caption at 0</li>
<li data-index="1" data-start="10000">Caption at 10000</li>
<li data-index="2" data-start="20000">Caption at 20000</li>
<li data-index="3" data-start="30000">Caption at 30000</li>
'''
.
replace
(
/\n/g
,
''
))
captionsData
=
jasmine
.
stubbedCaption
$
(
'.subtitles li[data-index]'
).
each
(
index
,
link
)
=>
expect
(
$
(
link
)).
toHaveData
'index'
,
index
expect
(
$
(
link
)).
toHaveData
'start'
,
captionsData
.
start
[
index
]
expect
(
$
(
link
)).
toHaveText
captionsData
.
text
[
index
]
it
'add a padding element to caption'
,
->
expect
(
$
(
'.subtitles li:first'
)).
toBe
'.spacing'
...
...
@@ -66,9 +73,11 @@ xdescribe 'VideoCaption', ->
expect
(
@
caption
.
rendered
).
toBeTruthy
()
describe
'when on a touch-based device'
,
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
true
@
caption
=
new
VideoCaption
el
:
$
(
'.video'
),
youtubeId
:
'def456'
,
currentSpeed
:
'1.0'
window
.
onTouchBasedDevice
.
andReturn
true
@
player
=
jasmine
.
stubVideoPlayer
@
@
caption
=
@
player
.
caption
it
'show explaination message'
,
->
expect
(
$
(
'.subtitles li'
)).
toHaveHtml
"Caption will be displayed when you start playing the video."
...
...
@@ -77,12 +86,15 @@ xdescribe 'VideoCaption', ->
expect
(
@
caption
.
rendered
).
toBeFalsy
()
describe
'mouse movement'
,
->
beforeEach
->
spyOn
(
window
,
'setTimeout'
).
andReturn
100
@
player
=
jasmine
.
stubVideoPlayer
@
@
caption
=
@
player
.
caption
window
.
setTimeout
.
andReturn
(
100
)
spyOn
window
,
'clearTimeout'
@
caption
=
new
VideoCaption
el
:
$
(
'.video'
),
youtubeId
:
'def456'
,
currentSpeed
:
'1.0'
describe
'when cursor is outside of the caption box'
,
->
beforeEach
->
$
(
window
).
trigger
jQuery
.
Event
'mousemove'
...
...
@@ -90,6 +102,7 @@ xdescribe 'VideoCaption', ->
expect
(
@
caption
.
frozen
).
toBeFalsy
()
describe
'when cursor is in the caption box'
,
->
beforeEach
->
$
(
'.subtitles'
).
trigger
jQuery
.
Event
'mouseenter'
...
...
@@ -143,8 +156,10 @@ xdescribe 'VideoCaption', ->
expect
(
$
.
fn
.
scrollTo
).
not
.
toHaveBeenCalled
()
describe
'search'
,
->
beforeEach
->
@
caption
=
new
VideoCaption
el
:
$
(
'.video'
),
youtubeId
:
'def456'
,
currentSpeed
:
'1.0'
@
player
=
jasmine
.
stubVideoPlayer
@
@
caption
=
@
player
.
caption
it
'return a correct caption index'
,
->
expect
(
@
caption
.
search
(
0
)).
toEqual
0
...
...
@@ -157,17 +172,17 @@ xdescribe 'VideoCaption', ->
describe
'play'
,
->
describe
'when the caption was not rendered'
,
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
true
@
caption
=
new
VideoCaption
el
:
$
(
'.video'
),
youtubeId
:
'def456'
,
currentSpeed
:
'1.0'
window
.
onTouchBasedDevice
.
andReturn
true
@
player
=
jasmine
.
stubVideoPlayer
@
@
caption
=
@
player
.
caption
@
caption
.
play
()
it
'render the caption'
,
->
expect
(
$
(
'.subtitles'
).
html
()).
toMatch
new
RegExp
(
'''<li data-index="0" data-start="0">Caption at 0</li>'''
+
'''<li data-index="1" data-start="10000">Caption at 10000</li>'''
+
'''<li data-index="2" data-start="20000">Caption at 20000</li>'''
+
'''<li data-index="3" data-start="30000">Caption at 30000</li>'''
)
captionsData
=
jasmine
.
stubbedCaption
$
(
'.subtitles li[data-index]'
).
each
(
index
,
link
)
=>
expect
(
$
(
link
)).
toHaveData
'index'
,
index
expect
(
$
(
link
)).
toHaveData
'start'
,
captionsData
.
start
[
index
]
expect
(
$
(
link
)).
toHaveText
captionsData
.
text
[
index
]
it
'add a padding element to caption'
,
->
expect
(
$
(
'.subtitles li:first'
)).
toBe
'.spacing'
...
...
@@ -185,7 +200,8 @@ xdescribe 'VideoCaption', ->
describe
'pause'
,
->
beforeEach
->
@
caption
=
new
VideoCaption
el
:
$
(
'.video'
),
youtubeId
:
'def456'
,
currentSpeed
:
'1.0'
@
player
=
jasmine
.
stubVideoPlayer
@
@
caption
=
@
player
.
caption
@
caption
.
playing
=
true
@
caption
.
pause
()
...
...
@@ -193,8 +209,10 @@ xdescribe 'VideoCaption', ->
expect
(
@
caption
.
playing
).
toBeFalsy
()
describe
'updatePlayTime'
,
->
beforeEach
->
@
caption
=
new
VideoCaption
el
:
$
(
'.video'
),
youtubeId
:
'def456'
,
currentSpeed
:
'1.0'
@
player
=
jasmine
.
stubVideoPlayer
@
@
caption
=
@
player
.
caption
describe
'when the video speed is 1.0x'
,
->
beforeEach
->
...
...
@@ -240,26 +258,29 @@ xdescribe 'VideoCaption', ->
expect
(
$
(
'.subtitles li[data-index=1]'
)).
toHaveClass
'current'
describe
'resize'
,
->
beforeEach
->
@
caption
=
new
VideoCaption
el
:
$
(
'.video'
),
youtubeId
:
'def456'
,
currentSpeed
:
'1.0'
@
player
=
jasmine
.
stubVideoPlayer
@
@
caption
=
@
player
.
caption
$
(
'.subtitles li[data-index=1]'
).
addClass
'current'
@
caption
.
resize
()
it
'set the height of caption container'
,
->
expect
(
parseInt
(
$
(
'.subtitles'
).
css
(
'maxHeight'
))).
to
Equal
$
(
'.video-wrapper'
).
height
()
expect
(
parseInt
(
$
(
'.subtitles'
).
css
(
'maxHeight'
))).
to
BeCloseTo
$
(
'.video-wrapper'
).
height
(),
2
it
'set the height of caption spacing'
,
->
expect
(
parseInt
(
$
(
'.subtitles .spacing:first'
).
css
(
'height'
))).
toEqual
(
$
(
'.video-wrapper'
).
height
()
/
2
-
$
(
'.subtitles li:not(.spacing):first'
).
height
()
/
2
)
expect
(
parseInt
(
$
(
'.subtitles .spacing:last'
).
css
(
'height'
))).
toEqual
(
$
(
'.video-wrapper'
).
height
()
/
2
-
$
(
'.subtitles li:not(.spacing):last'
).
height
()
/
2
)
expect
(
Math
.
abs
(
parseInt
(
$
(
'.subtitles .spacing:first'
).
css
(
'height'
))
-
@
caption
.
topSpacingHeight
())).
toBeLessThan
1
expect
(
Math
.
abs
(
parseInt
(
$
(
'.subtitles .spacing:last'
).
css
(
'height'
))
-
@
caption
.
bottomSpacingHeight
())).
toBeLessThan
1
it
'scroll caption to new position'
,
->
expect
(
$
.
fn
.
scrollTo
).
toHaveBeenCalled
()
describe
'scrollCaption'
,
->
beforeEach
->
@
caption
=
new
VideoCaption
el
:
$
(
'.video'
),
youtubeId
:
'def456'
,
currentSpeed
:
'1.0'
@
player
=
jasmine
.
stubVideoPlayer
@
@
caption
=
@
player
.
caption
describe
'when frozen'
,
->
beforeEach
->
...
...
@@ -291,15 +312,17 @@ xdescribe 'VideoCaption', ->
offset
:
-
(
$
(
'.video-wrapper'
).
height
()
/
2
-
$
(
'.subtitles .current:first'
).
height
()
/
2
)
describe
'seekPlayer'
,
->
beforeEach
->
@
caption
=
new
VideoCaption
el
:
$
(
'.video'
),
youtubeId
:
'def456'
,
currentSpeed
:
'1.0'
@
player
=
jasmine
.
stubVideoPlayer
@
@
caption
=
@
player
.
caption
@
time
=
null
$
(
@
caption
).
bind
'seek'
,
(
event
,
time
)
=>
@
time
=
time
describe
'when the video speed is 1.0x'
,
->
beforeEach
->
@
caption
.
currentSpeed
=
'1.0'
$
(
'.subtitles li[data-start="30000"]'
).
click
(
)
$
(
'.subtitles li[data-start="30000"]'
).
trigger
(
'click'
)
it
'trigger seek event with the correct time'
,
->
expect
(
@
time
).
toEqual
30.000
...
...
@@ -307,14 +330,15 @@ xdescribe 'VideoCaption', ->
describe
'when the video speed is not 1.0x'
,
->
beforeEach
->
@
caption
.
currentSpeed
=
'0.75'
$
(
'.subtitles li[data-start="30000"]'
).
click
(
)
$
(
'.subtitles li[data-start="30000"]'
).
trigger
(
'click'
)
it
'trigger seek event with the correct time'
,
->
expect
(
@
time
).
toEqual
40.000
describe
'toggle'
,
->
beforeEach
->
@
caption
=
new
VideoCaption
el
:
$
(
'.video'
),
youtubeId
:
'def456'
,
currentSpeed
:
'1.0'
@
player
=
jasmine
.
stubVideoPlayer
@
@
caption
=
@
player
.
caption
$
(
'.subtitles li[data-index=1]'
).
addClass
'current'
describe
'when the caption is visible'
,
->
...
...
@@ -325,7 +349,6 @@ xdescribe 'VideoCaption', ->
it
'hide the caption'
,
->
expect
(
@
caption
.
el
).
toHaveClass
'closed'
describe
'when the caption is hidden'
,
->
beforeEach
->
@
caption
.
el
.
addClass
'closed'
...
...
common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee
View file @
de1c6879
# TODO: figure out why failing
xdescribe
'VideoControl'
,
->
describe
'VideoControl'
,
->
beforeEach
->
jasmine
.
stubVideoPlayer
@
window
.
onTouchBasedDevice
=
jasmine
.
createSpy
(
'onTouchBasedDevice'
).
andReturn
false
loadFixtures
'video.html'
$
(
'.video-controls'
).
html
''
describe
'constructor'
,
->
it
'render the video controls'
,
->
new
VideoControl
(
el
:
$
(
'.video-controls'
))
expect
(
$
(
'.video-controls'
).
html
()).
toContain
'''
<div class="slider"></div>
<div>
<ul class="vcr">
<li><a class="video_control play" href="#">Play</a></li>
<li>
<div class="vidtime">0:00 / 0:00</div>
</li>
</ul>
<div class="secondary-controls">
<a href="#" class="add-fullscreen" title="Fill browser">Fill Browser</a>
</div>
</div>
'''
@
control
=
new
window
.
VideoControl
(
el
:
$
(
'.video-controls'
))
expect
(
$
(
'.video-controls'
)).
toContain
[
'.slider'
,
'ul.vcr'
,
'a.play'
,
'.vidtime'
,
'.add-fullscreen'
].
join
(
','
)
expect
(
$
(
'.video-controls'
).
find
(
'.vidtime'
)).
toHaveText
'0:00 / 0:00'
it
'bind the playback button'
,
->
control
=
new
VideoControl
(
el
:
$
(
'.video-controls'
))
expect
(
$
(
'.video_control'
)).
toHandleWith
'click'
,
control
.
togglePlayback
@
control
=
new
window
.
VideoControl
(
el
:
$
(
'.video-controls'
))
expect
(
$
(
'.video_control'
)).
toHandleWith
'click'
,
@
control
.
togglePlayback
describe
'when on a touch based device'
,
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
true
window
.
onTouchBasedDevice
.
andReturn
true
@
control
=
new
window
.
VideoControl
(
el
:
$
(
'.video-controls'
))
it
'does not add the play class to video control'
,
->
new
VideoControl
(
el
:
$
(
'.video-controls'
))
expect
(
$
(
'.video_control'
)).
not
.
toHaveClass
'play'
expect
(
$
(
'.video_control'
)).
not
.
toHaveHtml
'Play'
describe
'when on a non-touch based device'
,
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
false
@
control
=
new
window
.
VideoControl
(
el
:
$
(
'.video-controls'
))
it
'add the play class to video control'
,
->
new
VideoControl
(
el
:
$
(
'.video-controls'
))
expect
(
$
(
'.video_control'
)).
toHaveClass
'play'
expect
(
$
(
'.video_control'
)).
toHaveHtml
'Play'
describe
'play'
,
->
beforeEach
->
@
control
=
new
VideoControl
(
el
:
$
(
'.video-controls'
))
@
control
=
new
window
.
VideoControl
(
el
:
$
(
'.video-controls'
))
@
control
.
play
()
it
'switch playback button to play state'
,
->
...
...
@@ -56,8 +47,9 @@ xdescribe 'VideoControl', ->
expect
(
$
(
'.video_control'
)).
toHaveHtml
'Pause'
describe
'pause'
,
->
beforeEach
->
@
control
=
new
VideoControl
(
el
:
$
(
'.video-controls'
))
@
control
=
new
window
.
VideoControl
(
el
:
$
(
'.video-controls'
))
@
control
.
pause
()
it
'switch playback button to pause state'
,
->
...
...
@@ -66,8 +58,9 @@ xdescribe 'VideoControl', ->
expect
(
$
(
'.video_control'
)).
toHaveHtml
'Play'
describe
'togglePlayback'
,
->
beforeEach
->
@
control
=
new
VideoControl
(
el
:
$
(
'.video-controls'
))
@
control
=
new
window
.
VideoControl
(
el
:
$
(
'.video-controls'
))
describe
'when the control does not have play or pause class'
,
->
beforeEach
->
...
...
common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee
View file @
de1c6879
# TODO: figure out why failing
xdescribe
'VideoPlayer'
,
->
describe
'VideoPlayer'
,
->
beforeEach
->
window
.
onTouchBasedDevice
=
jasmine
.
createSpy
(
'onTouchBasedDevice'
).
andReturn
false
# It tries to call methods of VideoProgressSlider on Spy
for
part
in
[
'VideoCaption'
,
'VideoSpeedControl'
,
'VideoVolumeControl'
,
'VideoProgressSlider'
,
'VideoControl'
]
spyOn
(
window
[
part
].
prototype
,
'initialize'
).
andCallThrough
()
jasmine
.
stubVideoPlayer
@
,
[],
false
afterEach
->
...
...
@@ -8,7 +11,6 @@ xdescribe 'VideoPlayer', ->
describe
'constructor'
,
->
beforeEach
->
spyOn
window
,
'VideoControl'
spyOn
YT
,
'Player'
$
.
fn
.
qtip
.
andCallFake
->
$
(
this
).
data
(
'qtip'
,
true
)
...
...
@@ -22,32 +24,47 @@ xdescribe 'VideoPlayer', ->
expect
(
@
player
.
currentTime
).
toEqual
0
it
'set the element'
,
->
expect
(
@
player
.
el
).
to
Be
'#video_example
'
expect
(
@
player
.
el
).
to
HaveId
'video_id
'
it
'create video control'
,
->
expect
(
window
.
VideoControl
).
toHaveBeenCalledWith
el
:
$
(
'.video-controls'
,
@
player
.
el
)
expect
(
window
.
VideoControl
.
prototype
.
initialize
).
toHaveBeenCalled
()
expect
(
@
player
.
control
).
toBeDefined
()
expect
(
@
player
.
control
.
el
).
toBe
$
(
'.video-controls'
,
@
player
.
el
)
it
'create video caption'
,
->
expect
(
window
.
VideoCaption
).
toHaveBeenCalledWith
el
:
@
player
.
el
,
youtubeId
:
'normalSpeedYoutubeId'
,
currentSpeed
:
'1.0'
expect
(
window
.
VideoCaption
.
prototype
.
initialize
).
toHaveBeenCalled
()
expect
(
@
player
.
caption
).
toBeDefined
()
expect
(
@
player
.
caption
.
el
).
toBe
@
player
.
el
expect
(
@
player
.
caption
.
youtubeId
).
toEqual
'normalSpeedYoutubeId'
expect
(
@
player
.
caption
.
currentSpeed
).
toEqual
'1.0'
expect
(
@
player
.
caption
.
captionAssetPath
).
toEqual
'/static/subs/'
it
'create video speed control'
,
->
expect
(
window
.
VideoSpeedControl
).
toHaveBeenCalledWith
el
:
$
(
'.secondary-controls'
,
@
player
.
el
),
speeds
:
[
'0.75'
,
'1.0'
],
currentSpeed
:
'1.0'
expect
(
window
.
VideoSpeedControl
.
prototype
.
initialize
).
toHaveBeenCalled
()
expect
(
@
player
.
speedControl
).
toBeDefined
()
expect
(
@
player
.
speedControl
.
el
).
toBe
$
(
'.secondary-controls'
,
@
player
.
el
)
expect
(
@
player
.
speedControl
.
speeds
).
toEqual
[
'0.75'
,
'1.0'
]
expect
(
@
player
.
speedControl
.
currentSpeed
).
toEqual
'1.0'
it
'create video progress slider'
,
->
expect
(
window
.
VideoProgressSlider
).
toHaveBeenCalledWith
el
:
$
(
'.slider'
,
@
player
.
el
)
expect
(
window
.
VideoSpeedControl
.
prototype
.
initialize
).
toHaveBeenCalled
()
expect
(
@
player
.
progressSlider
).
toBeDefined
()
expect
(
@
player
.
progressSlider
.
el
).
toBe
$
(
'.slider'
,
@
player
.
el
)
it
'create Youtube player'
,
->
expect
(
YT
.
Player
).
toHaveBeenCalledWith
(
'
example
'
,
{
expect
(
YT
.
Player
).
toHaveBeenCalledWith
(
'
id
'
,
{
playerVars
:
controls
:
0
wmode
:
'transparent'
rel
:
0
showinfo
:
0
enablejsapi
:
1
modestbranding
:
1
videoId
:
'normalSpeedYoutubeId'
events
:
onReady
:
@
player
.
onReady
onStateChange
:
@
player
.
onStateChange
onPlaybackQualityChange
:
@
player
.
onPlaybackQualityChange
})
it
'bind to video control play event'
,
->
...
...
@@ -69,14 +86,13 @@ xdescribe 'VideoPlayer', ->
expect
(
$
(
@
player
.
volumeControl
)).
toHandleWith
'volumeChange'
,
@
player
.
onVolumeChange
it
'bind to key press'
,
->
expect
(
$
(
document
)).
toHandleWith
'keyup'
,
@
player
.
bindExitFullScreen
expect
(
$
(
document
.
documentElement
)).
toHandleWith
'keyup'
,
@
player
.
bindExitFullScreen
it
'bind to fullscreen switching button'
,
->
expect
(
$
(
'.add-fullscreen'
)).
toHandleWith
'click'
,
@
player
.
toggleFullScreen
describe
'when not on a touch based device'
,
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
false
$
(
'.add-fullscreen, .hide-subtitles'
).
removeData
'qtip'
@
player
=
new
VideoPlayer
video
:
@
video
...
...
@@ -85,11 +101,13 @@ xdescribe 'VideoPlayer', ->
expect
(
$
(
'.hide-subtitles'
)).
toHaveData
'qtip'
it
'create video volume control'
,
->
expect
(
window
.
VideoVolumeControl
).
toHaveBeenCalledWith
el
:
$
(
'.secondary-controls'
,
@
player
.
el
)
expect
(
window
.
VideoVolumeControl
.
prototype
.
initialize
).
toHaveBeenCalled
()
expect
(
@
player
.
volumeControl
).
toBeDefined
()
expect
(
@
player
.
volumeControl
.
el
).
toBe
$
(
'.secondary-controls'
,
@
player
.
el
)
describe
'when on a touch based device'
,
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
)
.
andReturn
true
window
.
onTouchBasedDevice
.
andReturn
true
$
(
'.add-fullscreen, .hide-subtitles'
).
removeData
'qtip'
@
player
=
new
VideoPlayer
video
:
@
video
...
...
@@ -98,7 +116,8 @@ xdescribe 'VideoPlayer', ->
expect
(
$
(
'.hide-subtitles'
)).
not
.
toHaveData
'qtip'
it
'does not create video volume control'
,
->
expect
(
window
.
VideoVolumeControl
).
not
.
toHaveBeenCalled
()
expect
(
window
.
VideoVolumeControl
.
prototype
.
initialize
).
not
.
toHaveBeenCalled
()
expect
(
@
player
.
volumeControl
).
not
.
toBeDefined
()
describe
'onReady'
,
->
beforeEach
->
...
...
@@ -110,7 +129,6 @@ xdescribe 'VideoPlayer', ->
describe
'when not on a touch based device'
,
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
false
spyOn
@
player
,
'play'
@
player
.
onReady
()
...
...
@@ -119,7 +137,7 @@ xdescribe 'VideoPlayer', ->
describe
'when on a touch based device'
,
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
)
.
andReturn
true
window
.
onTouchBasedDevice
.
andReturn
true
spyOn
@
player
,
'play'
@
player
.
onReady
()
...
...
@@ -347,9 +365,6 @@ xdescribe 'VideoPlayer', ->
it
'replace the full screen button tooltip'
,
->
expect
(
$
(
'.add-fullscreen'
)).
toHaveAttr
'title'
,
'Exit fill browser'
it
'add a new exit from fullscreen button'
,
->
expect
(
@
player
.
el
).
toContain
'a.exit'
it
'add the fullscreen class'
,
->
expect
(
@
player
.
el
).
toHaveClass
'fullscreen'
...
...
@@ -438,7 +453,7 @@ xdescribe 'VideoPlayer', ->
describe
'volume'
,
->
beforeEach
->
@
player
=
new
VideoPlayer
@
video
@
player
=
new
VideoPlayer
video
:
@
video
@
player
.
player
.
getVolume
.
andReturn
42
describe
'without value'
,
->
...
...
common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee
View file @
de1c6879
# TODO: figure out why failing
xdescribe
'VideoProgressSlider'
,
->
describe
'VideoProgressSlider'
,
->
beforeEach
->
jasmine
.
stubVideoPlayer
@
window
.
onTouchBasedDevice
=
jasmine
.
createSpy
(
'onTouchBasedDevice'
).
andReturn
false
describe
'constructor'
,
->
describe
'on a non-touch based device'
,
->
beforeEach
->
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
false
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
player
=
jasmine
.
stubVideoPlayer
@
@
progressSlider
=
@
player
.
progressSlider
it
'build the slider'
,
->
expect
(
@
s
lider
.
slider
).
toBe
'.slider'
expect
(
@
progressS
lider
.
slider
).
toBe
'.slider'
expect
(
$
.
fn
.
slider
).
toHaveBeenCalledWith
range
:
'min'
change
:
@
s
lider
.
onChange
slide
:
@
s
lider
.
onSlide
stop
:
@
s
lider
.
onStop
change
:
@
progressS
lider
.
onChange
slide
:
@
progressS
lider
.
onSlide
stop
:
@
progressS
lider
.
onStop
it
'build the seek handle'
,
->
expect
(
@
s
lider
.
handle
).
toBe
'.slider .ui-slider-handle'
expect
(
@
progressS
lider
.
handle
).
toBe
'.slider .ui-slider-handle'
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalledWith
content
:
"0:00"
position
:
my
:
'bottom center'
at
:
'top center'
container
:
@
s
lider
.
handle
container
:
@
progressS
lider
.
handle
hide
:
delay
:
700
style
:
...
...
@@ -34,47 +33,51 @@ xdescribe 'VideoProgressSlider', ->
describe
'on a touch-based device'
,
->
beforeEach
->
window
.
onTouchBasedDevice
.
andReturn
true
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
true
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
player
=
jasmine
.
stubVideoPlayer
@
@
progressSlider
=
@
player
.
progressSlider
it
'does not build the slider'
,
->
expect
(
@
s
lider
.
slider
).
toBeUndefined
expect
(
@
progressS
lider
.
slider
).
toBeUndefined
expect
(
$
.
fn
.
slider
).
not
.
toHaveBeenCalled
()
describe
'play'
,
->
beforeEach
->
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
spyOn
(
VideoProgressSlider
.
prototype
,
'buildSlider'
).
andCallThrough
()
@
player
=
jasmine
.
stubVideoPlayer
@
@
progressSlider
=
@
player
.
progressSlider
describe
'when the slider was already built'
,
->
beforeEach
->
@
s
lider
.
play
()
@
progressS
lider
.
play
()
it
'does not build the slider'
,
->
expect
(
$
.
fn
.
slider
).
not
.
toHaveBeenCalled
expect
(
@
progressSlider
.
buildSlider
.
calls
.
length
).
toEqual
1
describe
'when the slider was not already built'
,
->
beforeEach
->
@
slider
.
slider
=
null
@
slider
.
play
()
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
@
progressSlider
.
slider
=
null
@
progressSlider
.
play
()
it
'build the slider'
,
->
expect
(
@
s
lider
.
slider
).
toBe
'.slider'
expect
(
@
progressS
lider
.
slider
).
toBe
'.slider'
expect
(
$
.
fn
.
slider
).
toHaveBeenCalledWith
range
:
'min'
change
:
@
s
lider
.
onChange
slide
:
@
s
lider
.
onSlide
stop
:
@
s
lider
.
onStop
change
:
@
progressS
lider
.
onChange
slide
:
@
progressS
lider
.
onSlide
stop
:
@
progressS
lider
.
onStop
it
'build the seek handle'
,
->
expect
(
@
s
lider
.
handle
).
toBe
'.ui-slider-handle'
expect
(
@
progressS
lider
.
handle
).
toBe
'.ui-slider-handle'
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalledWith
content
:
"0:00"
position
:
my
:
'bottom center'
at
:
'top center'
container
:
@
s
lider
.
handle
container
:
@
progressS
lider
.
handle
hide
:
delay
:
700
style
:
...
...
@@ -83,21 +86,23 @@ xdescribe 'VideoProgressSlider', ->
describe
'updatePlayTime'
,
->
beforeEach
->
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
@
player
=
jasmine
.
stubVideoPlayer
@
@
progressSlider
=
@
player
.
progressSlider
describe
'when frozen'
,
->
beforeEach
->
@
slider
.
frozen
=
true
@
slider
.
updatePlayTime
20
,
120
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
@
progressSlider
.
frozen
=
true
@
progressSlider
.
updatePlayTime
20
,
120
it
'does not update the slider'
,
->
expect
(
$
.
fn
.
slider
).
not
.
toHaveBeenCalled
()
describe
'when not frozen'
,
->
beforeEach
->
@
slider
.
frozen
=
false
@
slider
.
updatePlayTime
20
,
120
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
@
progressSlider
.
frozen
=
false
@
progressSlider
.
updatePlayTime
20
,
120
it
'update the max value of the slider'
,
->
expect
(
$
.
fn
.
slider
).
toHaveBeenCalledWith
'option'
,
'max'
,
120
...
...
@@ -107,55 +112,58 @@ xdescribe 'VideoProgressSlider', ->
describe
'onSlide'
,
->
beforeEach
->
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
player
=
jasmine
.
stubVideoPlayer
@
@
progressSlider
=
@
player
.
progressSlider
@
time
=
null
$
(
@
s
lider
).
bind
'seek'
,
(
event
,
time
)
=>
@
time
=
time
spyOnEvent
@
s
lider
,
'seek'
@
s
lider
.
onSlide
{},
value
:
20
$
(
@
progressS
lider
).
bind
'seek'
,
(
event
,
time
)
=>
@
time
=
time
spyOnEvent
@
progressS
lider
,
'seek'
@
progressS
lider
.
onSlide
{},
value
:
20
it
'freeze the slider'
,
->
expect
(
@
s
lider
.
frozen
).
toBeTruthy
()
expect
(
@
progressS
lider
.
frozen
).
toBeTruthy
()
it
'update the tooltip'
,
->
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalled
()
it
'trigger seek event'
,
->
expect
(
'seek'
).
toHaveBeenTriggeredOn
@
s
lider
expect
(
'seek'
).
toHaveBeenTriggeredOn
@
progressS
lider
expect
(
@
time
).
toEqual
20
describe
'onChange'
,
->
beforeEach
->
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
slider
.
onChange
{},
value
:
20
@
player
=
jasmine
.
stubVideoPlayer
@
@
progressSlider
=
@
player
.
progressSlider
@
progressSlider
.
onChange
{},
value
:
20
it
'update the tooltip'
,
->
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalled
()
describe
'onStop'
,
->
beforeEach
->
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
player
=
jasmine
.
stubVideoPlayer
@
@
progressSlider
=
@
player
.
progressSlider
@
time
=
null
$
(
@
slider
).
bind
'seek'
,
(
event
,
time
)
=>
@
time
=
time
spyOnEvent
@
slider
,
'seek'
spyOn
(
window
,
'setTimeout'
)
@
slider
.
onStop
{},
value
:
20
$
(
@
progressSlider
).
bind
'seek'
,
(
event
,
time
)
=>
@
time
=
time
spyOnEvent
@
progressSlider
,
'seek'
@
progressSlider
.
onStop
{},
value
:
20
it
'freeze the slider'
,
->
expect
(
@
s
lider
.
frozen
).
toBeTruthy
()
expect
(
@
progressS
lider
.
frozen
).
toBeTruthy
()
it
'trigger seek event'
,
->
expect
(
'seek'
).
toHaveBeenTriggeredOn
@
s
lider
expect
(
'seek'
).
toHaveBeenTriggeredOn
@
progressS
lider
expect
(
@
time
).
toEqual
20
it
'set timeout to unfreeze the slider'
,
->
expect
(
window
.
setTimeout
).
toHaveBeenCalledWith
jasmine
.
any
(
Function
),
200
window
.
setTimeout
.
mostRecentCall
.
args
[
0
]()
expect
(
@
s
lider
.
frozen
).
toBeFalsy
()
expect
(
@
progressS
lider
.
frozen
).
toBeFalsy
()
describe
'updateTooltip'
,
->
beforeEach
->
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
slider
.
updateTooltip
90
@
player
=
jasmine
.
stubVideoPlayer
@
@
progressSlider
=
@
player
.
progressSlider
@
progressSlider
.
updateTooltip
90
it
'set the tooltip value'
,
->
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalledWith
'option'
,
'content.text'
,
'1:30'
common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee
View file @
de1c6879
# TODO: figure out why failing
xdescribe
'VideoSpeedControl'
,
->
describe
'VideoSpeedControl'
,
->
beforeEach
->
window
.
onTouchBasedDevice
=
jasmine
.
createSpy
(
'onTouchBasedDevice'
).
andReturn
false
jasmine
.
stubVideoPlayer
@
$
(
'.speeds'
).
remove
()
...
...
@@ -10,22 +10,23 @@ xdescribe 'VideoSpeedControl', ->
@
speedControl
=
new
VideoSpeedControl
el
:
$
(
'.secondary-controls'
),
speeds
:
@
video
.
speeds
,
currentSpeed
:
'1.0'
it
'add the video speed control to player'
,
->
expect
(
$
(
'.secondary-controls'
).
html
()).
toContain
'''
<div class="speeds">
<a href="#">
<h3>Speed</h3>
<p class="active">1.0x</p>
</a>
<ol class="video_speeds"><li data-speed="1.0" class="active"><a href="#">1.0x</a></li><li data-speed="0.75"><a href="#">0.75x</a></li></ol>
</div>
'''
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'
,
@
speedControl
.
currentSpeed
expect
(
li
.
length
).
toBe
@
speedControl
.
speeds
.
length
$
.
each
li
.
toArray
().
reverse
(),
(
index
,
link
)
=>
expect
(
$
(
link
)).
toHaveData
'speed'
,
@
speedControl
.
speeds
[
index
]
expect
(
$
(
link
).
find
(
'a'
).
text
()).
toBe
@
speedControl
.
speeds
[
index
]
+
'x'
it
'bind to change video speed link'
,
->
expect
(
$
(
'.video_speeds a'
)).
toHandleWith
'click'
,
@
speedControl
.
changeVideoSpeed
describe
'when running on touch based device'
,
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
)
.
andReturn
true
window
.
onTouchBasedDevice
.
andReturn
true
$
(
'.speeds'
).
removeClass
'open'
@
speedControl
=
new
VideoSpeedControl
el
:
$
(
'.secondary-controls'
),
speeds
:
@
video
.
speeds
,
currentSpeed
:
'1.0'
...
...
@@ -37,7 +38,6 @@ xdescribe 'VideoSpeedControl', ->
describe
'when running on non-touch based device'
,
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
false
$
(
'.speeds'
).
removeClass
'open'
@
speedControl
=
new
VideoSpeedControl
el
:
$
(
'.secondary-controls'
),
speeds
:
@
video
.
speeds
,
currentSpeed
:
'1.0'
...
...
common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee
View file @
de1c6879
# TODO: figure out why failing
xdescribe
'VideoVolumeControl'
,
->
describe
'VideoVolumeControl'
,
->
beforeEach
->
jasmine
.
stubVideoPlayer
@
$
(
'.volume'
).
remove
()
...
...
common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee
View file @
de1c6879
# TODO: figure out why failing
xdescribe
'Video'
,
->
describe
'Video'
,
->
metadata
=
undefined
beforeEach
->
loadFixtures
'video.html'
jasmine
.
stubRequests
()
@
videosDefinition
=
'.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId'
@
videosDefinition
=
'
0
.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId'
@
slowerSpeedYoutubeId
=
'slowerSpeedYoutubeId'
@
normalSpeedYoutubeId
=
'normalSpeedYoutubeId'
metadata
=
slowerSpeedYoutubeId
:
id
:
@
slowerSpeedYoutubeId
duration
:
300
normalSpeedYoutubeId
:
id
:
@
normalSpeedYoutubeId
duration
:
200
afterEach
->
window
.
player
=
undefined
...
...
@@ -16,17 +24,18 @@ xdescribe 'Video', ->
beforeEach
->
@
stubVideoPlayer
=
jasmine
.
createSpy
(
'VideoPlayer'
)
$
.
cookie
.
andReturn
'0.75'
window
.
player
=
100
window
.
player
=
undefined
describe
'by default'
,
->
beforeEach
->
@
video
=
new
Video
'example'
,
@
videosDefinition
spyOn
(
window
.
Video
.
prototype
,
'fetchMetadata'
).
andCallFake
->
@
metadata
=
metadata
@
video
=
new
Video
'#example'
,
@
videosDefinition
it
'reset the current video player'
,
->
expect
(
window
.
player
).
toBeNull
()
it
'set the elements'
,
->
expect
(
@
video
.
el
).
toBe
'#video_
example
'
expect
(
@
video
.
el
).
toBe
'#video_
id
'
it
'parse the videos'
,
->
expect
(
@
video
.
videos
).
toEqual
...
...
@@ -34,13 +43,8 @@ xdescribe 'Video', ->
'1.0'
:
@
normalSpeedYoutubeId
it
'fetch the video metadata'
,
->
expect
(
@
video
.
metadata
).
toEqual
slowerSpeedYoutubeId
:
id
:
@
slowerSpeedYoutubeId
duration
:
300
normalSpeedYoutubeId
:
id
:
@
normalSpeedYoutubeId
duration
:
200
expect
(
@
video
.
fetchMetadata
).
toHaveBeenCalled
expect
(
@
video
.
metadata
).
toEqual
metadata
it
'parse available video speeds'
,
->
expect
(
@
video
.
speeds
).
toEqual
[
'0.75'
,
'1.0'
]
...
...
@@ -56,7 +60,7 @@ xdescribe 'Video', ->
@
originalYT
=
window
.
YT
window
.
YT
=
{
Player
:
true
}
spyOn
(
window
,
'VideoPlayer'
).
andReturn
(
@
stubVideoPlayer
)
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
afterEach
->
window
.
YT
=
@
originalYT
...
...
@@ -69,7 +73,7 @@ xdescribe 'Video', ->
beforeEach
->
@
originalYT
=
window
.
YT
window
.
YT
=
{}
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
afterEach
->
window
.
YT
=
@
originalYT
...
...
@@ -82,7 +86,7 @@ xdescribe 'Video', ->
@
originalYT
=
window
.
YT
window
.
YT
=
{}
spyOn
(
window
,
'VideoPlayer'
).
andReturn
(
@
stubVideoPlayer
)
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
window
.
onYouTubePlayerAPIReady
()
afterEach
->
...
...
@@ -95,7 +99,7 @@ xdescribe 'Video', ->
describe
'youtubeId'
,
->
beforeEach
->
$
.
cookie
.
andReturn
'1.0'
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
describe
'with speed'
,
->
it
'return the video id for given speed'
,
->
...
...
@@ -108,7 +112,7 @@ xdescribe 'Video', ->
describe
'setSpeed'
,
->
beforeEach
->
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
describe
'when new speed is available'
,
->
beforeEach
->
...
...
@@ -129,14 +133,14 @@ xdescribe 'Video', ->
describe
'getDuration'
,
->
beforeEach
->
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
it
'return duration for current video'
,
->
expect
(
@
video
.
getDuration
()).
toEqual
200
describe
'log'
,
->
beforeEach
->
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
@
video
.
setSpeed
'1.0'
spyOn
Logger
,
'log'
@
video
.
player
=
{
currentTime
:
25
}
...
...
@@ -144,7 +148,7 @@ xdescribe 'Video', ->
it
'call the logger with valid parameters'
,
->
expect
(
Logger
.
log
).
toHaveBeenCalledWith
'someEvent'
,
id
:
'
example
'
id
:
'
id
'
code
:
@
normalSpeedYoutubeId
currentTime
:
25
speed
:
'1.0'
common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee
View file @
de1c6879
...
...
@@ -37,7 +37,7 @@ class @VideoCaption extends Subview
@
loaded
=
true
if
onTouchBasedDevice
()
$
(
'.subtitles
li'
).
html
"Caption will be displayed when you start playing the video.
"
$
(
'.subtitles
'
).
html
"<li>Caption will be displayed when you start playing the video.</li>
"
else
@
renderCaption
()
...
...
common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee
View file @
de1c6879
...
...
@@ -15,7 +15,7 @@ class @VideoPlayer extends Subview
$
(
@
progressSlider
).
bind
(
'seek'
,
@
onSeek
)
if
@
volumeControl
$
(
@
volumeControl
).
bind
(
'volumeChange'
,
@
onVolumeChange
)
$
(
document
).
keyup
@
bindExitFullScreen
$
(
document
.
documentElement
).
keyup
@
bindExitFullScreen
@
$
(
'.add-fullscreen'
).
click
@
toggleFullScreen
@
addToolTip
()
unless
onTouchBasedDevice
()
...
...
common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee
View file @
de1c6879
...
...
@@ -11,7 +11,7 @@ class @VideoProgressSlider extends Subview
@
buildHandle
()
buildHandle
:
->
@
handle
=
@
$
(
'.
slider .
ui-slider-handle'
)
@
handle
=
@
$
(
'.ui-slider-handle'
)
@
handle
.
qtip
content
:
"
#{
Time
.
format
(
@
slider
.
slider
(
'value'
))
}
"
position
:
...
...
common/lib/xmodule/xmodule/video_module.py
View file @
de1c6879
# pylint: disable=W0223
"""Video is ungraded Xmodule for support video content."""
import
json
import
logging
...
...
@@ -8,7 +11,6 @@ from django.http import Http404
from
xmodule.x_module
import
XModule
from
xmodule.raw_module
import
RawDescriptor
from
xmodule.contentstore.content
import
StaticContent
from
xblock.core
import
Integer
,
Scope
,
String
import
datetime
...
...
@@ -18,21 +20,26 @@ log = logging.getLogger(__name__)
class
VideoFields
(
object
):
"""Fields for `VideoModule` and `VideoDescriptor`."""
data
=
String
(
help
=
"XML data for the problem"
,
scope
=
Scope
.
content
)
position
=
Integer
(
help
=
"Current position in the video"
,
scope
=
Scope
.
user_state
,
default
=
0
)
class
VideoModule
(
VideoFields
,
XModule
):
"""Video Xmodule."""
video_time
=
0
icon_class
=
'video'
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/time.coffee'
),
resource_string
(
__name__
,
'js/src/video/display.coffee'
)]
+
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/time.coffee'
),
resource_string
(
__name__
,
'js/src/video/display.coffee'
)
]
+
[
resource_string
(
__name__
,
'js/src/video/display/'
+
filename
)
for
filename
in
sorted
(
resource_listdir
(
__name__
,
'js/src/video/display'
))
if
filename
.
endswith
(
'.coffee'
)]}
if
filename
.
endswith
(
'.coffee'
)]
}
css
=
{
'scss'
:
[
resource_string
(
__name__
,
'css/video/display.scss'
)]}
js_module_name
=
"Video"
...
...
@@ -44,14 +51,14 @@ class VideoModule(VideoFields, XModule):
self
.
show_captions
=
xmltree
.
get
(
'show_captions'
,
'true'
)
self
.
source
=
self
.
_get_source
(
xmltree
)
self
.
track
=
self
.
_get_track
(
xmltree
)
self
.
start_time
,
self
.
end_time
=
self
.
_
get_timeframe
(
xmltree
)
self
.
start_time
,
self
.
end_time
=
self
.
get_timeframe
(
xmltree
)
def
_get_source
(
self
,
xmltree
):
# find the first valid source
"""Find the first valid source."""
return
self
.
_get_first_external
(
xmltree
,
'source'
)
def
_get_track
(
self
,
xmltree
):
# find the first valid track
"""Find the first valid track."""
return
self
.
_get_first_external
(
xmltree
,
'track'
)
def
_get_first_external
(
self
,
xmltree
,
tag
):
...
...
@@ -68,52 +75,37 @@ class VideoModule(VideoFields, XModule):
break
return
result
def
_
get_timeframe
(
self
,
xmltree
):
def
get_timeframe
(
self
,
xmltree
):
""" Converts 'from' and 'to' parameters in video tag to seconds.
If there are no parameters, returns empty string. """
def
parse_time
(
s
):
def
parse_time
(
s
tr_time
):
"""Converts s in '12:34:45' format to seconds. If s is
None, returns empty string"""
if
s
is
None
:
if
s
tr_time
is
None
:
return
''
else
:
x
=
time
.
strptime
(
s
,
'
%
H:
%
M:
%
S'
)
return
datetime
.
timedelta
(
hours
=
x
.
tm_hour
,
minutes
=
x
.
tm_min
,
seconds
=
x
.
tm_sec
)
.
total_seconds
()
obj_time
=
time
.
strptime
(
str_time
,
'
%
H:
%
M:
%
S'
)
return
datetime
.
timedelta
(
hours
=
obj_time
.
tm_hour
,
minutes
=
obj_time
.
tm_min
,
seconds
=
obj_time
.
tm_sec
)
.
total_seconds
()
return
parse_time
(
xmltree
.
get
(
'from'
)),
parse_time
(
xmltree
.
get
(
'to'
))
def
handle_ajax
(
self
,
dispatch
,
get
):
'''
Handle ajax calls to this video.
TODO (vshnayder): This is not being called right now, so the position
is not being saved.
'''
"""This is not being called right now and we raise 404 error."""
log
.
debug
(
u"GET {0}"
.
format
(
get
))
log
.
debug
(
u"DISPATCH {0}"
.
format
(
dispatch
))
if
dispatch
==
'goto_position'
:
self
.
position
=
int
(
float
(
get
[
'position'
]))
log
.
info
(
u"NEW POSITION {0}"
.
format
(
self
.
position
))
return
json
.
dumps
({
'success'
:
True
})
raise
Http404
()
def
get_progress
(
self
):
''' TODO (vshnayder): Get and save duration of youtube video, then return
fraction watched.
(Be careful to notice when video link changes and update)
For now, we have no way of knowing if the video has even been watched, so
just return None.
'''
return
None
def
get_instance_state
(
self
):
#log.debug(u"STATE POSITION {0}".format(self.position))
"""Return information about state (position)."""
return
json
.
dumps
({
'position'
:
self
.
position
})
def
video_list
(
self
):
"""Return video list."""
return
self
.
youtube
def
get_html
(
self
):
...
...
@@ -144,6 +136,7 @@ class VideoModule(VideoFields, XModule):
class
VideoDescriptor
(
VideoFields
,
RawDescriptor
):
"""Descriptor for `VideoModule`."""
module_class
=
VideoModule
stores_state
=
True
template_dir_name
=
"video"
lms/djangoapps/courseware/tests/__init__.py
View file @
de1c6879
"""
integration tests for xmodule
Contains:
1. BaseTestXmodule class provides course and users
for testing Xmodules with mongo store.
"""
from
django.test.utils
import
override_settings
from
django.core.urlresolvers
import
reverse
from
django.test.client
import
Client
from
student.tests.factories
import
UserFactory
,
CourseEnrollmentFactory
from
courseware.tests.tests
import
TEST_DATA_MONGO_MODULESTORE
from
xmodule.tests
import
test_system
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
)
class
BaseTestXmodule
(
ModuleStoreTestCase
):
"""Base class for testing Xmodules with mongo store.
This class prepares course and users for tests:
1. create test course
2. create, enrol and login users for this course
Any xmodule should overwrite only next parameters for test:
1. TEMPLATE_NAME
2. DATA
3. MODEL_DATA
4. COURSE_DATA and USER_COUNT if needed
This class should not contain any tests, because TEMPLATE_NAME
should be defined in child class.
"""
USER_COUNT
=
2
COURSE_DATA
=
{}
# Data from YAML common/lib/xmodule/xmodule/templates/NAME/default.yaml
TEMPLATE_NAME
=
""
DATA
=
''
MODEL_DATA
=
{
'data'
:
'<some_module></some_module>'
}
def
setUp
(
self
):
self
.
course
=
CourseFactory
.
create
(
data
=
self
.
COURSE_DATA
)
# Turn off cache.
modulestore
()
.
request_cache
=
None
modulestore
()
.
metadata_inheritance_cache_subsystem
=
None
chapter
=
ItemFactory
.
create
(
parent_location
=
self
.
course
.
location
,
template
=
"i4x://edx/templates/sequential/Empty"
,
)
section
=
ItemFactory
.
create
(
parent_location
=
chapter
.
location
,
template
=
"i4x://edx/templates/sequential/Empty"
)
# username = robot{0}, password = 'test'
self
.
users
=
[
UserFactory
.
create
(
username
=
'robot
%
d'
%
i
,
email
=
'robot+test+
%
d@edx.org'
%
i
)
for
i
in
range
(
self
.
USER_COUNT
)
]
for
user
in
self
.
users
:
CourseEnrollmentFactory
.
create
(
user
=
user
,
course_id
=
self
.
course
.
id
)
self
.
item_descriptor
=
ItemFactory
.
create
(
parent_location
=
section
.
location
,
template
=
self
.
TEMPLATE_NAME
,
data
=
self
.
DATA
)
location
=
self
.
item_descriptor
.
location
system
=
test_system
()
system
.
render_template
=
lambda
template
,
context
:
context
self
.
item_module
=
self
.
item_descriptor
.
module_class
(
system
,
location
,
self
.
item_descriptor
,
self
.
MODEL_DATA
)
self
.
item_url
=
Location
(
location
)
.
url
()
# login all users for acces to Xmodule
self
.
clients
=
{
user
.
username
:
Client
()
for
user
in
self
.
users
}
self
.
login_statuses
=
[
self
.
clients
[
user
.
username
]
.
login
(
username
=
user
.
username
,
password
=
'test'
)
for
user
in
self
.
users
]
self
.
assertTrue
(
all
(
self
.
login_statuses
))
def
get_url
(
self
,
dispatch
):
"""Return item url with dispatch."""
return
reverse
(
'modx_dispatch'
,
args
=
(
self
.
course
.
id
,
self
.
item_url
,
dispatch
)
)
def
tearDown
(
self
):
for
user
in
self
.
users
:
user
.
delete
()
lms/djangoapps/courseware/tests/test_video_mongo.py
0 → 100644
View file @
de1c6879
# -*- coding: utf-8 -*-
"""Video xmodule tests in mongo."""
from
.
import
BaseTestXmodule
class
TestVideo
(
BaseTestXmodule
):
"""Integration tests: web client + mongo."""
TEMPLATE_NAME
=
"i4x://edx/templates/video/default"
DATA
=
'<video youtube="0.75:JMD_ifUUfsU,1.0:OEoXaMPEzfM,1.25:AKqURZnYqpk,1.50:DYpADpL7jAY"/>'
def
test_handle_ajax_dispatch
(
self
):
responses
=
{
user
.
username
:
self
.
clients
[
user
.
username
]
.
post
(
self
.
get_url
(
'whatever'
),
{},
HTTP_X_REQUESTED_WITH
=
'XMLHttpRequest'
)
for
user
in
self
.
users
}
self
.
assertEqual
(
set
([
response
.
status_code
for
_
,
response
in
responses
.
items
()
])
.
pop
(),
404
)
lms/djangoapps/courseware/tests/test_video_xml.py
0 → 100644
View file @
de1c6879
# -*- coding: utf-8 -*-
"""Test for Video Xmodule functional logic.
These tests data readed from xml, not from mongo.
We have a ModuleStoreTestCase class defined in
common/lib/xmodule/xmodule/modulestore/tests/django_utils.py.
You can search for usages of this in the cms and lms tests for examples.
You use this so that it will do things like point the modulestore
setting to mongo, flush the contentstore before and after, load the
templates, etc.
You can then use the CourseFactory and XModuleItemFactory as defined in
common/lib/xmodule/xmodule/modulestore/tests/factories.py to create the
course, section, subsection, unit, etc.
"""
import
json
import
unittest
from
mock
import
Mock
from
lxml
import
etree
from
xmodule.video_module
import
VideoDescriptor
,
VideoModule
from
xmodule.modulestore
import
Location
from
xmodule.tests
import
test_system
from
xmodule.tests.test_logic
import
LogicTest
class
VideoFactory
(
object
):
"""A helper class to create video modules with various parameters
for testing.
"""
# tag that uses youtube videos
sample_problem_xml_youtube
=
"""
<video show_captions="true"
youtube="0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg"
data_dir=""
caption_asset_path=""
autoplay="true"
from="01:00:03" to="01:00:10"
>
<source src=".../mit-3091x/M-3091X-FA12-L21-3_100.mp4"/>
</video>
"""
@staticmethod
def
create
():
"""Method return Video Xmodule instance."""
location
=
Location
([
"i4x"
,
"edX"
,
"video"
,
"default"
,
"SampleProblem1"
])
model_data
=
{
'data'
:
VideoFactory
.
sample_problem_xml_youtube
}
descriptor
=
Mock
(
weight
=
"1"
)
system
=
test_system
()
system
.
render_template
=
lambda
template
,
context
:
context
module
=
VideoModule
(
system
,
location
,
descriptor
,
model_data
)
return
module
class
VideoModuleLogicTest
(
LogicTest
):
"""Tests for logic of Video Xmodule."""
descriptor_class
=
VideoDescriptor
raw_model_data
=
{
'data'
:
'<video />'
}
def
test_get_timeframe_no_parameters
(
self
):
"""Make sure that timeframe() works correctly w/o parameters"""
xmltree
=
etree
.
fromstring
(
'<video>test</video>'
)
output
=
self
.
xmodule
.
get_timeframe
(
xmltree
)
self
.
assertEqual
(
output
,
(
''
,
''
))
def
test_get_timeframe_with_one_parameter
(
self
):
"""Make sure that timeframe() works correctly with one parameter"""
xmltree
=
etree
.
fromstring
(
'<video from="00:04:07">test</video>'
)
output
=
self
.
xmodule
.
get_timeframe
(
xmltree
)
self
.
assertEqual
(
output
,
(
247
,
''
))
def
test_get_timeframe_with_two_parameters
(
self
):
"""Make sure that timeframe() works correctly with two parameters"""
xmltree
=
etree
.
fromstring
(
'''<video
from="00:04:07"
to="13:04:39"
>test</video>'''
)
output
=
self
.
xmodule
.
get_timeframe
(
xmltree
)
self
.
assertEqual
(
output
,
(
247
,
47079
))
class
VideoModuleUnitTest
(
unittest
.
TestCase
):
"""Unit tests for Video Xmodule."""
def
test_video_constructor
(
self
):
"""Make sure that all parameters extracted correclty from xml"""
module
=
VideoFactory
.
create
()
# `get_html` return only context, cause we
# overwrite `system.render_template`
context
=
module
.
get_html
()
expected_context
=
{
'track'
:
None
,
'show_captions'
:
'true'
,
'display_name'
:
'SampleProblem1'
,
'id'
:
module
.
location
.
html_id
(),
'end'
:
3610.0
,
'caption_asset_path'
:
'/static/subs/'
,
'source'
:
'.../mit-3091x/M-3091X-FA12-L21-3_100.mp4'
,
'streams'
:
'0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg'
,
'normal_speed_video_id'
:
'ZwkTiUPN0mg'
,
'position'
:
0
,
'start'
:
3603.0
}
self
.
assertDictEqual
(
context
,
expected_context
)
self
.
assertEqual
(
module
.
youtube
,
'0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg'
)
self
.
assertEqual
(
module
.
video_list
(),
module
.
youtube
)
self
.
assertEqual
(
module
.
position
,
0
)
self
.
assertDictEqual
(
json
.
loads
(
module
.
get_instance_state
()),
{
'position'
:
0
})
lms/static/sass/base/_variables.scss
View file @
de1c6879
...
...
@@ -88,9 +88,10 @@ $dashboard-profile-header-color: transparent;
$dashboard-profile-color
:
rgb
(
252
,
252
,
252
);
$dot-color
:
$light-gray
;
$content-wrapper-bg
:
shade
(
$body-bg
,
2%
)
;
$content-wrapper-bg
:
$white
;
$course-bg-color
:
#d6d6d6
;
$course-bg-image
:
url(../images/bg-texture.png)
;
$account-content-wrapper-bg
:
shade
(
$body-bg
,
2%
);
$course-profile-bg
:
rgb
(
245
,
245
,
245
);
$course-header-bg
:
rgba
(
255
,
255
,
255
,
0
.93
);
...
...
lms/static/sass/course/base/_base.scss
View file @
de1c6879
...
...
@@ -35,7 +35,7 @@ a {
width
:
100%
;
border-radius
:
3px
;
border
:
1px
solid
$outer-border-color
;
background
:
$
body
-bg
;
background
:
$
container
-bg
;
@include
box-shadow
(
0
1px
2px
rgba
(
0
,
0
,
0
,
0
.05
));
}
}
...
...
@@ -50,7 +50,7 @@ textarea,
input
[
type
=
"text"
],
input
[
type
=
"email"
],
input
[
type
=
"password"
]
{
background
:
$
body-bg
;
background
:
$
white
;
border
:
1px
solid
$border-color-2
;
@include
border-radius
(
0
);
@include
box-shadow
(
0
1px
0
0
rgba
(
255
,
255
,
255
,
0
.6
)
,
inset
0
0
3px
0
rgba
(
0
,
0
,
0
,
0
.1
));
...
...
lms/static/sass/multicourse/_account.scss
View file @
de1c6879
...
...
@@ -6,7 +6,7 @@
// page-level
.view-register
,
.view-login
,
.view-passwordreset
{
background
:
$
body
-bg
;
background
:
$
container
-bg
;
...
...
@@ -98,7 +98,7 @@
// layout
.content-wrapper
{
background
:
$content-wrapper-bg
;
background
:
$
account-
content-wrapper-bg
;
padding-bottom
:
0
;
}
...
...
@@ -331,7 +331,7 @@
}
textarea
,
input
{
background
:
$
body
-bg
;
background
:
$
container
-bg
;
color
:
rgba
(
0
,
0
,
0
,.
25
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment