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
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
609 additions
and
244 deletions
+609
-244
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
+19
-9
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
+29
-36
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):
...
@@ -24,6 +24,30 @@ class LMSLinksTestCase(TestCase):
with
mock
.
patch
.
dict
(
'django.conf.settings.MITX_FEATURES'
,
{
'ENABLE_MKTG_SITE'
:
False
}):
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"
)
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
)
@override_settings
(
LMS_BASE
=
None
)
def
about_page_no_lms_base_test
(
self
):
def
about_page_no_lms_base_test
(
self
):
""" No LMS_BASE, nor is ENABLE_MKTG_SITE True """
""" 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
...
@@ -4,6 +4,10 @@ from xmodule.modulestore.django import modulestore
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
import
copy
import
copy
import
logging
import
re
log
=
logging
.
getLogger
(
__name__
)
DIRECT_ONLY_CATEGORIES
=
[
'course'
,
'chapter'
,
'sequential'
,
'about'
,
'static_tab'
,
'course_info'
]
DIRECT_ONLY_CATEGORIES
=
[
'course'
,
'chapter'
,
'sequential'
,
'about'
,
'static_tab'
,
'course_info'
]
...
@@ -108,9 +112,20 @@ def get_lms_link_for_about_page(location):
...
@@ -108,9 +112,20 @@ def get_lms_link_for_about_page(location):
Returns the url to the course about page from the location tuple.
Returns the url to the course about page from the location tuple.
"""
"""
if
settings
.
MITX_FEATURES
.
get
(
'ENABLE_MKTG_SITE'
,
False
):
if
settings
.
MITX_FEATURES
.
get
(
'ENABLE_MKTG_SITE'
,
False
):
# Root will be "www.edx.org". The complete URL will still not be exactly correct,
if
not
hasattr
(
settings
,
'MKTG_URLS'
):
# but redirects exist from www.edx.org to get to the drupal course about page URL.
log
.
exception
(
"ENABLE_MKTG_SITE is True, but MKTG_URLS is not defined."
)
about_base
=
settings
.
MKTG_URLS
.
get
(
'ROOT'
)
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
:
elif
settings
.
LMS_BASE
is
not
None
:
about_base
=
settings
.
LMS_BASE
about_base
=
settings
.
LMS_BASE
else
:
else
:
...
...
cms/envs/aws.py
View file @
de1c6879
...
@@ -103,6 +103,7 @@ DEFAULT_FROM_EMAIL = ENV_TOKENS.get('DEFAULT_FROM_EMAIL', DEFAULT_FROM_EMAIL)
...
@@ -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
)
DEFAULT_FEEDBACK_EMAIL
=
ENV_TOKENS
.
get
(
'DEFAULT_FEEDBACK_EMAIL'
,
DEFAULT_FEEDBACK_EMAIL
)
ADMINS
=
ENV_TOKENS
.
get
(
'ADMINS'
,
ADMINS
)
ADMINS
=
ENV_TOKENS
.
get
(
'ADMINS'
,
ADMINS
)
SERVER_EMAIL
=
ENV_TOKENS
.
get
(
'SERVER_EMAIL'
,
SERVER_EMAIL
)
SERVER_EMAIL
=
ENV_TOKENS
.
get
(
'SERVER_EMAIL'
,
SERVER_EMAIL
)
MKTG_URLS
=
ENV_TOKENS
.
get
(
'MKTG_URLS'
,
MKTG_URLS
)
#Timezone overrides
#Timezone overrides
TIME_ZONE
=
ENV_TOKENS
.
get
(
'TIME_ZONE'
,
TIME_ZONE
)
TIME_ZONE
=
ENV_TOKENS
.
get
(
'TIME_ZONE'
,
TIME_ZONE
)
...
...
cms/envs/common.py
View file @
de1c6879
...
@@ -335,3 +335,14 @@ INSTALLED_APPS = (
...
@@ -335,3 +335,14 @@ INSTALLED_APPS = (
################# EDX MARKETING SITE ##################################
################# EDX MARKETING SITE ##################################
EDXMKTG_COOKIE_NAME
=
'edxloggedin'
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
...
@@ -4,13 +4,15 @@ from django.core.urlresolvers import reverse
from
django.conf
import
settings
from
django.conf
import
settings
from
mitxmako.shortcuts
import
marketing_link
from
mitxmako.shortcuts
import
marketing_link
from
mock
import
patch
from
mock
import
patch
from
nose.plugins.skip
import
SkipTest
class
ShortcutsTests
(
TestCase
):
class
ShortcutsTests
(
TestCase
):
"""
"""
Test the mitxmako shortcuts file
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_URLS
=
{
'ROOT'
:
'dummy-root'
,
'ABOUT'
:
'/about-us'
})
@override_settings
(
MKTG_URL_LINK_MAP
=
{
'ABOUT'
:
'login'
})
@override_settings
(
MKTG_URL_LINK_MAP
=
{
'ABOUT'
:
'login'
})
def
test_marketing_link
(
self
):
def
test_marketing_link
(
self
):
...
...
common/lib/xmodule/xmodule/js/fixtures/video.html
View file @
de1c6879
<div
class=
"course-content"
>
<div
class=
"course-content"
>
<div
id=
"video_example"
class=
"video"
>
<div
id=
"video_example"
>
<div
class=
"tc-wrapper"
>
<div
id=
"example"
>
<article
class=
"video-wrapper"
>
<div
id=
"video_id"
class=
"video"
<section
class=
"video-player"
>
data-streams=
"0.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId"
<div
id=
"example"
></div>
data-show-captions=
"true"
</section>
data-start=
""
<section
class=
"video-controls"
></section>
data-end=
""
</article>
data-caption-asset-path=
"/static/subs/"
>
<div
class=
"tc-wrapper"
>
<article
class=
"video-wrapper"
>
<section
class=
"video-player"
>
<div
id=
"id"
></div>
</section>
<section
class=
"video-controls"
></section>
</article>
</div>
</div>
</div>
</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 = ->
...
@@ -28,7 +28,7 @@ jasmine.stubRequests = ->
spyOn
(
$
,
'ajax'
).
andCallFake
(
settings
)
->
spyOn
(
$
,
'ajax'
).
andCallFake
(
settings
)
->
if
match
=
settings
.
url
.
match
/youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/
if
match
=
settings
.
url
.
match
/youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/
settings
.
success
data
:
jasmine
.
stubbedMetadata
[
match
[
1
]]
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
settings
.
success
jasmine
.
stubbedCaption
else
if
settings
.
url
.
match
/.+\/problem_get$/
else
if
settings
.
url
.
match
/.+\/problem_get$/
settings
.
success
html
:
readFixtures
(
'problem_content.html'
)
settings
.
success
html
:
readFixtures
(
'problem_content.html'
)
...
@@ -47,19 +47,15 @@ jasmine.stubYoutubePlayer = ->
...
@@ -47,19 +47,15 @@ jasmine.stubYoutubePlayer = ->
jasmine
.
stubVideoPlayer
=
(
context
,
enableParts
,
createPlayer
=
true
)
->
jasmine
.
stubVideoPlayer
=
(
context
,
enableParts
,
createPlayer
=
true
)
->
enableParts
=
[
enableParts
]
unless
$
.
isArray
(
enableParts
)
enableParts
=
[
enableParts
]
unless
$
.
isArray
(
enableParts
)
suite
=
context
.
suite
suite
=
context
.
suite
currentPartName
=
suite
.
description
while
suite
=
suite
.
parentSuite
currentPartName
=
suite
.
description
while
suite
=
suite
.
parentSuite
enableParts
.
push
currentPartName
enableParts
.
push
currentPartName
for
part
in
[
'VideoCaption'
,
'VideoSpeedControl'
,
'VideoVolumeControl'
,
'VideoProgressSlider'
]
unless
$
.
inArray
(
part
,
enableParts
)
>=
0
spyOn
window
,
part
loadFixtures
'video.html'
loadFixtures
'video.html'
jasmine
.
stubRequests
()
jasmine
.
stubRequests
()
YT
.
Player
=
undefined
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
()
jasmine
.
stubYoutubePlayer
()
if
createPlayer
if
createPlayer
return
new
VideoPlayer
(
video
:
context
.
video
)
return
new
VideoPlayer
(
video
:
context
.
video
)
...
...
common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee
View file @
de1c6879
This diff is collapsed.
Click to expand it.
common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee
View file @
de1c6879
# TODO: figure out why failing
describe
'VideoControl'
,
->
xdescribe
'VideoControl'
,
->
beforeEach
->
beforeEach
->
jasmine
.
stubVideoPlayer
@
window
.
onTouchBasedDevice
=
jasmine
.
createSpy
(
'onTouchBasedDevice'
).
andReturn
false
loadFixtures
'video.html'
$
(
'.video-controls'
).
html
''
$
(
'.video-controls'
).
html
''
describe
'constructor'
,
->
describe
'constructor'
,
->
it
'render the video controls'
,
->
it
'render the video controls'
,
->
new
VideoControl
(
el
:
$
(
'.video-controls'
))
@
control
=
new
window
.
VideoControl
(
el
:
$
(
'.video-controls'
))
expect
(
$
(
'.video-controls'
).
html
()).
toContain
'''
expect
(
$
(
'.video-controls'
)).
toContain
<div class="slider"></div>
[
'.slider'
,
'ul.vcr'
,
'a.play'
,
'.vidtime'
,
'.add-fullscreen'
].
join
(
','
)
<div>
expect
(
$
(
'.video-controls'
).
find
(
'.vidtime'
)).
toHaveText
'0:00 / 0:00'
<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>
'''
it
'bind the playback button'
,
->
it
'bind the playback button'
,
->
control
=
new
VideoControl
(
el
:
$
(
'.video-controls'
))
@
control
=
new
window
.
VideoControl
(
el
:
$
(
'.video-controls'
))
expect
(
$
(
'.video_control'
)).
toHandleWith
'click'
,
control
.
togglePlayback
expect
(
$
(
'.video_control'
)).
toHandleWith
'click'
,
@
control
.
togglePlayback
describe
'when on a touch based device'
,
->
describe
'when on a touch based device'
,
->
beforeEach
->
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'
,
->
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
.
toHaveClass
'play'
expect
(
$
(
'.video_control'
)).
not
.
toHaveHtml
'Play'
expect
(
$
(
'.video_control'
)).
not
.
toHaveHtml
'Play'
describe
'when on a non-touch based device'
,
->
describe
'when on a non-touch based device'
,
->
beforeEach
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
false
@
control
=
new
window
.
VideoControl
(
el
:
$
(
'.video-controls'
))
it
'add the play class to video control'
,
->
it
'add the play class to video control'
,
->
new
VideoControl
(
el
:
$
(
'.video-controls'
))
expect
(
$
(
'.video_control'
)).
toHaveClass
'play'
expect
(
$
(
'.video_control'
)).
toHaveClass
'play'
expect
(
$
(
'.video_control'
)).
toHaveHtml
'Play'
expect
(
$
(
'.video_control'
)).
toHaveHtml
'Play'
describe
'play'
,
->
describe
'play'
,
->
beforeEach
->
beforeEach
->
@
control
=
new
VideoControl
(
el
:
$
(
'.video-controls'
))
@
control
=
new
window
.
VideoControl
(
el
:
$
(
'.video-controls'
))
@
control
.
play
()
@
control
.
play
()
it
'switch playback button to play state'
,
->
it
'switch playback button to play state'
,
->
...
@@ -56,8 +47,9 @@ xdescribe 'VideoControl', ->
...
@@ -56,8 +47,9 @@ xdescribe 'VideoControl', ->
expect
(
$
(
'.video_control'
)).
toHaveHtml
'Pause'
expect
(
$
(
'.video_control'
)).
toHaveHtml
'Pause'
describe
'pause'
,
->
describe
'pause'
,
->
beforeEach
->
beforeEach
->
@
control
=
new
VideoControl
(
el
:
$
(
'.video-controls'
))
@
control
=
new
window
.
VideoControl
(
el
:
$
(
'.video-controls'
))
@
control
.
pause
()
@
control
.
pause
()
it
'switch playback button to pause state'
,
->
it
'switch playback button to pause state'
,
->
...
@@ -66,8 +58,9 @@ xdescribe 'VideoControl', ->
...
@@ -66,8 +58,9 @@ xdescribe 'VideoControl', ->
expect
(
$
(
'.video_control'
)).
toHaveHtml
'Play'
expect
(
$
(
'.video_control'
)).
toHaveHtml
'Play'
describe
'togglePlayback'
,
->
describe
'togglePlayback'
,
->
beforeEach
->
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'
,
->
describe
'when the control does not have play or pause class'
,
->
beforeEach
->
beforeEach
->
...
...
common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee
View file @
de1c6879
# TODO: figure out why failing
describe
'VideoPlayer'
,
->
xdescribe
'VideoPlayer'
,
->
beforeEach
->
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
jasmine
.
stubVideoPlayer
@
,
[],
false
afterEach
->
afterEach
->
...
@@ -8,7 +11,6 @@ xdescribe 'VideoPlayer', ->
...
@@ -8,7 +11,6 @@ xdescribe 'VideoPlayer', ->
describe
'constructor'
,
->
describe
'constructor'
,
->
beforeEach
->
beforeEach
->
spyOn
window
,
'VideoControl'
spyOn
YT
,
'Player'
spyOn
YT
,
'Player'
$
.
fn
.
qtip
.
andCallFake
->
$
.
fn
.
qtip
.
andCallFake
->
$
(
this
).
data
(
'qtip'
,
true
)
$
(
this
).
data
(
'qtip'
,
true
)
...
@@ -22,32 +24,47 @@ xdescribe 'VideoPlayer', ->
...
@@ -22,32 +24,47 @@ xdescribe 'VideoPlayer', ->
expect
(
@
player
.
currentTime
).
toEqual
0
expect
(
@
player
.
currentTime
).
toEqual
0
it
'set the element'
,
->
it
'set the element'
,
->
expect
(
@
player
.
el
).
to
Be
'#video_example
'
expect
(
@
player
.
el
).
to
HaveId
'video_id
'
it
'create video control'
,
->
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'
,
->
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'
,
->
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'
,
->
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'
,
->
it
'create Youtube player'
,
->
expect
(
YT
.
Player
).
toHaveBeenCalledWith
(
'
example
'
,
{
expect
(
YT
.
Player
).
toHaveBeenCalledWith
(
'
id
'
,
{
playerVars
:
playerVars
:
controls
:
0
controls
:
0
wmode
:
'transparent'
wmode
:
'transparent'
rel
:
0
rel
:
0
showinfo
:
0
showinfo
:
0
enablejsapi
:
1
enablejsapi
:
1
modestbranding
:
1
videoId
:
'normalSpeedYoutubeId'
videoId
:
'normalSpeedYoutubeId'
events
:
events
:
onReady
:
@
player
.
onReady
onReady
:
@
player
.
onReady
onStateChange
:
@
player
.
onStateChange
onStateChange
:
@
player
.
onStateChange
onPlaybackQualityChange
:
@
player
.
onPlaybackQualityChange
})
})
it
'bind to video control play event'
,
->
it
'bind to video control play event'
,
->
...
@@ -69,14 +86,13 @@ xdescribe 'VideoPlayer', ->
...
@@ -69,14 +86,13 @@ xdescribe 'VideoPlayer', ->
expect
(
$
(
@
player
.
volumeControl
)).
toHandleWith
'volumeChange'
,
@
player
.
onVolumeChange
expect
(
$
(
@
player
.
volumeControl
)).
toHandleWith
'volumeChange'
,
@
player
.
onVolumeChange
it
'bind to key press'
,
->
it
'bind to key press'
,
->
expect
(
$
(
document
)).
toHandleWith
'keyup'
,
@
player
.
bindExitFullScreen
expect
(
$
(
document
.
documentElement
)).
toHandleWith
'keyup'
,
@
player
.
bindExitFullScreen
it
'bind to fullscreen switching button'
,
->
it
'bind to fullscreen switching button'
,
->
expect
(
$
(
'.add-fullscreen'
)).
toHandleWith
'click'
,
@
player
.
toggleFullScreen
expect
(
$
(
'.add-fullscreen'
)).
toHandleWith
'click'
,
@
player
.
toggleFullScreen
describe
'when not on a touch based device'
,
->
describe
'when not on a touch based device'
,
->
beforeEach
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
false
$
(
'.add-fullscreen, .hide-subtitles'
).
removeData
'qtip'
$
(
'.add-fullscreen, .hide-subtitles'
).
removeData
'qtip'
@
player
=
new
VideoPlayer
video
:
@
video
@
player
=
new
VideoPlayer
video
:
@
video
...
@@ -85,11 +101,13 @@ xdescribe 'VideoPlayer', ->
...
@@ -85,11 +101,13 @@ xdescribe 'VideoPlayer', ->
expect
(
$
(
'.hide-subtitles'
)).
toHaveData
'qtip'
expect
(
$
(
'.hide-subtitles'
)).
toHaveData
'qtip'
it
'create video volume control'
,
->
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'
,
->
describe
'when on a touch based device'
,
->
beforeEach
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
)
.
andReturn
true
window
.
onTouchBasedDevice
.
andReturn
true
$
(
'.add-fullscreen, .hide-subtitles'
).
removeData
'qtip'
$
(
'.add-fullscreen, .hide-subtitles'
).
removeData
'qtip'
@
player
=
new
VideoPlayer
video
:
@
video
@
player
=
new
VideoPlayer
video
:
@
video
...
@@ -98,7 +116,8 @@ xdescribe 'VideoPlayer', ->
...
@@ -98,7 +116,8 @@ xdescribe 'VideoPlayer', ->
expect
(
$
(
'.hide-subtitles'
)).
not
.
toHaveData
'qtip'
expect
(
$
(
'.hide-subtitles'
)).
not
.
toHaveData
'qtip'
it
'does not create video volume control'
,
->
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'
,
->
describe
'onReady'
,
->
beforeEach
->
beforeEach
->
...
@@ -110,7 +129,6 @@ xdescribe 'VideoPlayer', ->
...
@@ -110,7 +129,6 @@ xdescribe 'VideoPlayer', ->
describe
'when not on a touch based device'
,
->
describe
'when not on a touch based device'
,
->
beforeEach
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
false
spyOn
@
player
,
'play'
spyOn
@
player
,
'play'
@
player
.
onReady
()
@
player
.
onReady
()
...
@@ -119,7 +137,7 @@ xdescribe 'VideoPlayer', ->
...
@@ -119,7 +137,7 @@ xdescribe 'VideoPlayer', ->
describe
'when on a touch based device'
,
->
describe
'when on a touch based device'
,
->
beforeEach
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
)
.
andReturn
true
window
.
onTouchBasedDevice
.
andReturn
true
spyOn
@
player
,
'play'
spyOn
@
player
,
'play'
@
player
.
onReady
()
@
player
.
onReady
()
...
@@ -347,9 +365,6 @@ xdescribe 'VideoPlayer', ->
...
@@ -347,9 +365,6 @@ xdescribe 'VideoPlayer', ->
it
'replace the full screen button tooltip'
,
->
it
'replace the full screen button tooltip'
,
->
expect
(
$
(
'.add-fullscreen'
)).
toHaveAttr
'title'
,
'Exit fill browser'
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'
,
->
it
'add the fullscreen class'
,
->
expect
(
@
player
.
el
).
toHaveClass
'fullscreen'
expect
(
@
player
.
el
).
toHaveClass
'fullscreen'
...
@@ -438,7 +453,7 @@ xdescribe 'VideoPlayer', ->
...
@@ -438,7 +453,7 @@ xdescribe 'VideoPlayer', ->
describe
'volume'
,
->
describe
'volume'
,
->
beforeEach
->
beforeEach
->
@
player
=
new
VideoPlayer
@
video
@
player
=
new
VideoPlayer
video
:
@
video
@
player
.
player
.
getVolume
.
andReturn
42
@
player
.
player
.
getVolume
.
andReturn
42
describe
'without value'
,
->
describe
'without value'
,
->
...
...
common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee
View file @
de1c6879
# TODO: figure out why failing
describe
'VideoProgressSlider'
,
->
xdescribe
'VideoProgressSlider'
,
->
beforeEach
->
beforeEach
->
jasmine
.
stubVideoPlayer
@
window
.
onTouchBasedDevice
=
jasmine
.
createSpy
(
'onTouchBasedDevice'
).
andReturn
false
describe
'constructor'
,
->
describe
'constructor'
,
->
describe
'on a non-touch based device'
,
->
describe
'on a non-touch based device'
,
->
beforeEach
->
beforeEach
->
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
false
@
player
=
jasmine
.
stubVideoPlayer
@
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
progressSlider
=
@
player
.
progressSlider
it
'build the slider'
,
->
it
'build the slider'
,
->
expect
(
@
s
lider
.
slider
).
toBe
'.slider'
expect
(
@
progressS
lider
.
slider
).
toBe
'.slider'
expect
(
$
.
fn
.
slider
).
toHaveBeenCalledWith
expect
(
$
.
fn
.
slider
).
toHaveBeenCalledWith
range
:
'min'
range
:
'min'
change
:
@
s
lider
.
onChange
change
:
@
progressS
lider
.
onChange
slide
:
@
s
lider
.
onSlide
slide
:
@
progressS
lider
.
onSlide
stop
:
@
s
lider
.
onStop
stop
:
@
progressS
lider
.
onStop
it
'build the seek handle'
,
->
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
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalledWith
content
:
"0:00"
content
:
"0:00"
position
:
position
:
my
:
'bottom center'
my
:
'bottom center'
at
:
'top center'
at
:
'top center'
container
:
@
s
lider
.
handle
container
:
@
progressS
lider
.
handle
hide
:
hide
:
delay
:
700
delay
:
700
style
:
style
:
...
@@ -34,47 +33,51 @@ xdescribe 'VideoProgressSlider', ->
...
@@ -34,47 +33,51 @@ xdescribe 'VideoProgressSlider', ->
describe
'on a touch-based device'
,
->
describe
'on a touch-based device'
,
->
beforeEach
->
beforeEach
->
window
.
onTouchBasedDevice
.
andReturn
true
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
true
@
player
=
jasmine
.
stubVideoPlayer
@
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
progressSlider
=
@
player
.
progressSlider
it
'does not build the slider'
,
->
it
'does not build the slider'
,
->
expect
(
@
s
lider
.
slider
).
toBeUndefined
expect
(
@
progressS
lider
.
slider
).
toBeUndefined
expect
(
$
.
fn
.
slider
).
not
.
toHaveBeenCalled
()
expect
(
$
.
fn
.
slider
).
not
.
toHaveBeenCalled
()
describe
'play'
,
->
describe
'play'
,
->
beforeEach
->
beforeEach
->
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
spyOn
(
VideoProgressSlider
.
prototype
,
'buildSlider'
).
andCallThrough
()
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
@
player
=
jasmine
.
stubVideoPlayer
@
@
progressSlider
=
@
player
.
progressSlider
describe
'when the slider was already built'
,
->
describe
'when the slider was already built'
,
->
beforeEach
->
beforeEach
->
@
s
lider
.
play
()
@
progressS
lider
.
play
()
it
'does not build the slider'
,
->
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'
,
->
describe
'when the slider was not already built'
,
->
beforeEach
->
beforeEach
->
@
slider
.
slider
=
null
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
@
slider
.
play
()
@
progressSlider
.
slider
=
null
@
progressSlider
.
play
()
it
'build the slider'
,
->
it
'build the slider'
,
->
expect
(
@
s
lider
.
slider
).
toBe
'.slider'
expect
(
@
progressS
lider
.
slider
).
toBe
'.slider'
expect
(
$
.
fn
.
slider
).
toHaveBeenCalledWith
expect
(
$
.
fn
.
slider
).
toHaveBeenCalledWith
range
:
'min'
range
:
'min'
change
:
@
s
lider
.
onChange
change
:
@
progressS
lider
.
onChange
slide
:
@
s
lider
.
onSlide
slide
:
@
progressS
lider
.
onSlide
stop
:
@
s
lider
.
onStop
stop
:
@
progressS
lider
.
onStop
it
'build the seek handle'
,
->
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
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalledWith
content
:
"0:00"
content
:
"0:00"
position
:
position
:
my
:
'bottom center'
my
:
'bottom center'
at
:
'top center'
at
:
'top center'
container
:
@
s
lider
.
handle
container
:
@
progressS
lider
.
handle
hide
:
hide
:
delay
:
700
delay
:
700
style
:
style
:
...
@@ -83,21 +86,23 @@ xdescribe 'VideoProgressSlider', ->
...
@@ -83,21 +86,23 @@ xdescribe 'VideoProgressSlider', ->
describe
'updatePlayTime'
,
->
describe
'updatePlayTime'
,
->
beforeEach
->
beforeEach
->
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
player
=
jasmine
.
stubVideoPlayer
@
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
@
progressSlider
=
@
player
.
progressSlider
describe
'when frozen'
,
->
describe
'when frozen'
,
->
beforeEach
->
beforeEach
->
@
slider
.
frozen
=
true
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
@
slider
.
updatePlayTime
20
,
120
@
progressSlider
.
frozen
=
true
@
progressSlider
.
updatePlayTime
20
,
120
it
'does not update the slider'
,
->
it
'does not update the slider'
,
->
expect
(
$
.
fn
.
slider
).
not
.
toHaveBeenCalled
()
expect
(
$
.
fn
.
slider
).
not
.
toHaveBeenCalled
()
describe
'when not frozen'
,
->
describe
'when not frozen'
,
->
beforeEach
->
beforeEach
->
@
slider
.
frozen
=
false
spyOn
(
$
.
fn
,
'slider'
).
andCallThrough
()
@
slider
.
updatePlayTime
20
,
120
@
progressSlider
.
frozen
=
false
@
progressSlider
.
updatePlayTime
20
,
120
it
'update the max value of the slider'
,
->
it
'update the max value of the slider'
,
->
expect
(
$
.
fn
.
slider
).
toHaveBeenCalledWith
'option'
,
'max'
,
120
expect
(
$
.
fn
.
slider
).
toHaveBeenCalledWith
'option'
,
'max'
,
120
...
@@ -107,55 +112,58 @@ xdescribe 'VideoProgressSlider', ->
...
@@ -107,55 +112,58 @@ xdescribe 'VideoProgressSlider', ->
describe
'onSlide'
,
->
describe
'onSlide'
,
->
beforeEach
->
beforeEach
->
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
player
=
jasmine
.
stubVideoPlayer
@
@
progressSlider
=
@
player
.
progressSlider
@
time
=
null
@
time
=
null
$
(
@
s
lider
).
bind
'seek'
,
(
event
,
time
)
=>
@
time
=
time
$
(
@
progressS
lider
).
bind
'seek'
,
(
event
,
time
)
=>
@
time
=
time
spyOnEvent
@
s
lider
,
'seek'
spyOnEvent
@
progressS
lider
,
'seek'
@
s
lider
.
onSlide
{},
value
:
20
@
progressS
lider
.
onSlide
{},
value
:
20
it
'freeze the slider'
,
->
it
'freeze the slider'
,
->
expect
(
@
s
lider
.
frozen
).
toBeTruthy
()
expect
(
@
progressS
lider
.
frozen
).
toBeTruthy
()
it
'update the tooltip'
,
->
it
'update the tooltip'
,
->
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalled
()
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalled
()
it
'trigger seek event'
,
->
it
'trigger seek event'
,
->
expect
(
'seek'
).
toHaveBeenTriggeredOn
@
s
lider
expect
(
'seek'
).
toHaveBeenTriggeredOn
@
progressS
lider
expect
(
@
time
).
toEqual
20
expect
(
@
time
).
toEqual
20
describe
'onChange'
,
->
describe
'onChange'
,
->
beforeEach
->
beforeEach
->
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
player
=
jasmine
.
stubVideoPlayer
@
@
slider
.
onChange
{},
value
:
20
@
progressSlider
=
@
player
.
progressSlider
@
progressSlider
.
onChange
{},
value
:
20
it
'update the tooltip'
,
->
it
'update the tooltip'
,
->
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalled
()
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalled
()
describe
'onStop'
,
->
describe
'onStop'
,
->
beforeEach
->
beforeEach
->
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
player
=
jasmine
.
stubVideoPlayer
@
@
progressSlider
=
@
player
.
progressSlider
@
time
=
null
@
time
=
null
$
(
@
slider
).
bind
'seek'
,
(
event
,
time
)
=>
@
time
=
time
$
(
@
progressSlider
).
bind
'seek'
,
(
event
,
time
)
=>
@
time
=
time
spyOnEvent
@
slider
,
'seek'
spyOnEvent
@
progressSlider
,
'seek'
spyOn
(
window
,
'setTimeout'
)
@
progressSlider
.
onStop
{},
value
:
20
@
slider
.
onStop
{},
value
:
20
it
'freeze the slider'
,
->
it
'freeze the slider'
,
->
expect
(
@
s
lider
.
frozen
).
toBeTruthy
()
expect
(
@
progressS
lider
.
frozen
).
toBeTruthy
()
it
'trigger seek event'
,
->
it
'trigger seek event'
,
->
expect
(
'seek'
).
toHaveBeenTriggeredOn
@
s
lider
expect
(
'seek'
).
toHaveBeenTriggeredOn
@
progressS
lider
expect
(
@
time
).
toEqual
20
expect
(
@
time
).
toEqual
20
it
'set timeout to unfreeze the slider'
,
->
it
'set timeout to unfreeze the slider'
,
->
expect
(
window
.
setTimeout
).
toHaveBeenCalledWith
jasmine
.
any
(
Function
),
200
expect
(
window
.
setTimeout
).
toHaveBeenCalledWith
jasmine
.
any
(
Function
),
200
window
.
setTimeout
.
mostRecentCall
.
args
[
0
]()
window
.
setTimeout
.
mostRecentCall
.
args
[
0
]()
expect
(
@
s
lider
.
frozen
).
toBeFalsy
()
expect
(
@
progressS
lider
.
frozen
).
toBeFalsy
()
describe
'updateTooltip'
,
->
describe
'updateTooltip'
,
->
beforeEach
->
beforeEach
->
@
slider
=
new
VideoProgressSlider
el
:
$
(
'.slider'
)
@
player
=
jasmine
.
stubVideoPlayer
@
@
slider
.
updateTooltip
90
@
progressSlider
=
@
player
.
progressSlider
@
progressSlider
.
updateTooltip
90
it
'set the tooltip value'
,
->
it
'set the tooltip value'
,
->
expect
(
$
.
fn
.
qtip
).
toHaveBeenCalledWith
'option'
,
'content.text'
,
'1:30'
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
describe
'VideoSpeedControl'
,
->
xdescribe
'VideoSpeedControl'
,
->
beforeEach
->
beforeEach
->
window
.
onTouchBasedDevice
=
jasmine
.
createSpy
(
'onTouchBasedDevice'
).
andReturn
false
jasmine
.
stubVideoPlayer
@
jasmine
.
stubVideoPlayer
@
$
(
'.speeds'
).
remove
()
$
(
'.speeds'
).
remove
()
...
@@ -10,22 +10,23 @@ xdescribe 'VideoSpeedControl', ->
...
@@ -10,22 +10,23 @@ xdescribe 'VideoSpeedControl', ->
@
speedControl
=
new
VideoSpeedControl
el
:
$
(
'.secondary-controls'
),
speeds
:
@
video
.
speeds
,
currentSpeed
:
'1.0'
@
speedControl
=
new
VideoSpeedControl
el
:
$
(
'.secondary-controls'
),
speeds
:
@
video
.
speeds
,
currentSpeed
:
'1.0'
it
'add the video speed control to player'
,
->
it
'add the video speed control to player'
,
->
expect
(
$
(
'.secondary-controls'
).
html
()).
toContain
'''
secondaryControls
=
$
(
'.secondary-controls'
)
<div class="speeds">
li
=
secondaryControls
.
find
(
'.video_speeds li'
)
<a href="#">
expect
(
secondaryControls
).
toContain
'.speeds'
<h3>Speed</h3>
expect
(
secondaryControls
).
toContain
'.video_speeds'
<p class="active">1.0x</p>
expect
(
secondaryControls
.
find
(
'p.active'
).
text
()).
toBe
'1.0x'
</a>
expect
(
li
.
filter
(
'.active'
)).
toHaveData
'speed'
,
@
speedControl
.
currentSpeed
<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>
expect
(
li
.
length
).
toBe
@
speedControl
.
speeds
.
length
</div>
$
.
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'
,
->
it
'bind to change video speed link'
,
->
expect
(
$
(
'.video_speeds a'
)).
toHandleWith
'click'
,
@
speedControl
.
changeVideoSpeed
expect
(
$
(
'.video_speeds a'
)).
toHandleWith
'click'
,
@
speedControl
.
changeVideoSpeed
describe
'when running on touch based device'
,
->
describe
'when running on touch based device'
,
->
beforeEach
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
)
.
andReturn
true
window
.
onTouchBasedDevice
.
andReturn
true
$
(
'.speeds'
).
removeClass
'open'
$
(
'.speeds'
).
removeClass
'open'
@
speedControl
=
new
VideoSpeedControl
el
:
$
(
'.secondary-controls'
),
speeds
:
@
video
.
speeds
,
currentSpeed
:
'1.0'
@
speedControl
=
new
VideoSpeedControl
el
:
$
(
'.secondary-controls'
),
speeds
:
@
video
.
speeds
,
currentSpeed
:
'1.0'
...
@@ -37,7 +38,6 @@ xdescribe 'VideoSpeedControl', ->
...
@@ -37,7 +38,6 @@ xdescribe 'VideoSpeedControl', ->
describe
'when running on non-touch based device'
,
->
describe
'when running on non-touch based device'
,
->
beforeEach
->
beforeEach
->
spyOn
(
window
,
'onTouchBasedDevice'
).
andReturn
false
$
(
'.speeds'
).
removeClass
'open'
$
(
'.speeds'
).
removeClass
'open'
@
speedControl
=
new
VideoSpeedControl
el
:
$
(
'.secondary-controls'
),
speeds
:
@
video
.
speeds
,
currentSpeed
:
'1.0'
@
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
describe
'VideoVolumeControl'
,
->
xdescribe
'VideoVolumeControl'
,
->
beforeEach
->
beforeEach
->
jasmine
.
stubVideoPlayer
@
jasmine
.
stubVideoPlayer
@
$
(
'.volume'
).
remove
()
$
(
'.volume'
).
remove
()
...
...
common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee
View file @
de1c6879
# TODO: figure out why failing
describe
'Video'
,
->
xdescribe
'Video'
,
->
metadata
=
undefined
beforeEach
->
beforeEach
->
loadFixtures
'video.html'
loadFixtures
'video.html'
jasmine
.
stubRequests
()
jasmine
.
stubRequests
()
@
videosDefinition
=
'.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId'
@
videosDefinition
=
'
0
.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId'
@
slowerSpeedYoutubeId
=
'slowerSpeedYoutubeId'
@
slowerSpeedYoutubeId
=
'slowerSpeedYoutubeId'
@
normalSpeedYoutubeId
=
'normalSpeedYoutubeId'
@
normalSpeedYoutubeId
=
'normalSpeedYoutubeId'
metadata
=
slowerSpeedYoutubeId
:
id
:
@
slowerSpeedYoutubeId
duration
:
300
normalSpeedYoutubeId
:
id
:
@
normalSpeedYoutubeId
duration
:
200
afterEach
->
afterEach
->
window
.
player
=
undefined
window
.
player
=
undefined
...
@@ -16,17 +24,18 @@ xdescribe 'Video', ->
...
@@ -16,17 +24,18 @@ xdescribe 'Video', ->
beforeEach
->
beforeEach
->
@
stubVideoPlayer
=
jasmine
.
createSpy
(
'VideoPlayer'
)
@
stubVideoPlayer
=
jasmine
.
createSpy
(
'VideoPlayer'
)
$
.
cookie
.
andReturn
'0.75'
$
.
cookie
.
andReturn
'0.75'
window
.
player
=
100
window
.
player
=
undefined
describe
'by default'
,
->
describe
'by default'
,
->
beforeEach
->
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'
,
->
it
'reset the current video player'
,
->
expect
(
window
.
player
).
toBeNull
()
expect
(
window
.
player
).
toBeNull
()
it
'set the elements'
,
->
it
'set the elements'
,
->
expect
(
@
video
.
el
).
toBe
'#video_
example
'
expect
(
@
video
.
el
).
toBe
'#video_
id
'
it
'parse the videos'
,
->
it
'parse the videos'
,
->
expect
(
@
video
.
videos
).
toEqual
expect
(
@
video
.
videos
).
toEqual
...
@@ -34,13 +43,8 @@ xdescribe 'Video', ->
...
@@ -34,13 +43,8 @@ xdescribe 'Video', ->
'1.0'
:
@
normalSpeedYoutubeId
'1.0'
:
@
normalSpeedYoutubeId
it
'fetch the video metadata'
,
->
it
'fetch the video metadata'
,
->
expect
(
@
video
.
metadata
).
toEqual
expect
(
@
video
.
fetchMetadata
).
toHaveBeenCalled
slowerSpeedYoutubeId
:
expect
(
@
video
.
metadata
).
toEqual
metadata
id
:
@
slowerSpeedYoutubeId
duration
:
300
normalSpeedYoutubeId
:
id
:
@
normalSpeedYoutubeId
duration
:
200
it
'parse available video speeds'
,
->
it
'parse available video speeds'
,
->
expect
(
@
video
.
speeds
).
toEqual
[
'0.75'
,
'1.0'
]
expect
(
@
video
.
speeds
).
toEqual
[
'0.75'
,
'1.0'
]
...
@@ -56,7 +60,7 @@ xdescribe 'Video', ->
...
@@ -56,7 +60,7 @@ xdescribe 'Video', ->
@
originalYT
=
window
.
YT
@
originalYT
=
window
.
YT
window
.
YT
=
{
Player
:
true
}
window
.
YT
=
{
Player
:
true
}
spyOn
(
window
,
'VideoPlayer'
).
andReturn
(
@
stubVideoPlayer
)
spyOn
(
window
,
'VideoPlayer'
).
andReturn
(
@
stubVideoPlayer
)
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
afterEach
->
afterEach
->
window
.
YT
=
@
originalYT
window
.
YT
=
@
originalYT
...
@@ -69,7 +73,7 @@ xdescribe 'Video', ->
...
@@ -69,7 +73,7 @@ xdescribe 'Video', ->
beforeEach
->
beforeEach
->
@
originalYT
=
window
.
YT
@
originalYT
=
window
.
YT
window
.
YT
=
{}
window
.
YT
=
{}
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
afterEach
->
afterEach
->
window
.
YT
=
@
originalYT
window
.
YT
=
@
originalYT
...
@@ -82,7 +86,7 @@ xdescribe 'Video', ->
...
@@ -82,7 +86,7 @@ xdescribe 'Video', ->
@
originalYT
=
window
.
YT
@
originalYT
=
window
.
YT
window
.
YT
=
{}
window
.
YT
=
{}
spyOn
(
window
,
'VideoPlayer'
).
andReturn
(
@
stubVideoPlayer
)
spyOn
(
window
,
'VideoPlayer'
).
andReturn
(
@
stubVideoPlayer
)
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
window
.
onYouTubePlayerAPIReady
()
window
.
onYouTubePlayerAPIReady
()
afterEach
->
afterEach
->
...
@@ -95,7 +99,7 @@ xdescribe 'Video', ->
...
@@ -95,7 +99,7 @@ xdescribe 'Video', ->
describe
'youtubeId'
,
->
describe
'youtubeId'
,
->
beforeEach
->
beforeEach
->
$
.
cookie
.
andReturn
'1.0'
$
.
cookie
.
andReturn
'1.0'
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
describe
'with speed'
,
->
describe
'with speed'
,
->
it
'return the video id for given speed'
,
->
it
'return the video id for given speed'
,
->
...
@@ -108,7 +112,7 @@ xdescribe 'Video', ->
...
@@ -108,7 +112,7 @@ xdescribe 'Video', ->
describe
'setSpeed'
,
->
describe
'setSpeed'
,
->
beforeEach
->
beforeEach
->
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
describe
'when new speed is available'
,
->
describe
'when new speed is available'
,
->
beforeEach
->
beforeEach
->
...
@@ -129,14 +133,14 @@ xdescribe 'Video', ->
...
@@ -129,14 +133,14 @@ xdescribe 'Video', ->
describe
'getDuration'
,
->
describe
'getDuration'
,
->
beforeEach
->
beforeEach
->
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
it
'return duration for current video'
,
->
it
'return duration for current video'
,
->
expect
(
@
video
.
getDuration
()).
toEqual
200
expect
(
@
video
.
getDuration
()).
toEqual
200
describe
'log'
,
->
describe
'log'
,
->
beforeEach
->
beforeEach
->
@
video
=
new
Video
'example'
,
@
videosDefinition
@
video
=
new
Video
'
#
example'
,
@
videosDefinition
@
video
.
setSpeed
'1.0'
@
video
.
setSpeed
'1.0'
spyOn
Logger
,
'log'
spyOn
Logger
,
'log'
@
video
.
player
=
{
currentTime
:
25
}
@
video
.
player
=
{
currentTime
:
25
}
...
@@ -144,7 +148,7 @@ xdescribe 'Video', ->
...
@@ -144,7 +148,7 @@ xdescribe 'Video', ->
it
'call the logger with valid parameters'
,
->
it
'call the logger with valid parameters'
,
->
expect
(
Logger
.
log
).
toHaveBeenCalledWith
'someEvent'
,
expect
(
Logger
.
log
).
toHaveBeenCalledWith
'someEvent'
,
id
:
'
example
'
id
:
'
id
'
code
:
@
normalSpeedYoutubeId
code
:
@
normalSpeedYoutubeId
currentTime
:
25
currentTime
:
25
speed
:
'1.0'
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
...
@@ -37,7 +37,7 @@ class @VideoCaption extends Subview
@
loaded
=
true
@
loaded
=
true
if
onTouchBasedDevice
()
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
else
@
renderCaption
()
@
renderCaption
()
...
...
common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee
View file @
de1c6879
...
@@ -15,7 +15,7 @@ class @VideoPlayer extends Subview
...
@@ -15,7 +15,7 @@ class @VideoPlayer extends Subview
$
(
@
progressSlider
).
bind
(
'seek'
,
@
onSeek
)
$
(
@
progressSlider
).
bind
(
'seek'
,
@
onSeek
)
if
@
volumeControl
if
@
volumeControl
$
(
@
volumeControl
).
bind
(
'volumeChange'
,
@
onVolumeChange
)
$
(
@
volumeControl
).
bind
(
'volumeChange'
,
@
onVolumeChange
)
$
(
document
).
keyup
@
bindExitFullScreen
$
(
document
.
documentElement
).
keyup
@
bindExitFullScreen
@
$
(
'.add-fullscreen'
).
click
@
toggleFullScreen
@
$
(
'.add-fullscreen'
).
click
@
toggleFullScreen
@
addToolTip
()
unless
onTouchBasedDevice
()
@
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
...
@@ -11,7 +11,7 @@ class @VideoProgressSlider extends Subview
@
buildHandle
()
@
buildHandle
()
buildHandle
:
->
buildHandle
:
->
@
handle
=
@
$
(
'.
slider .
ui-slider-handle'
)
@
handle
=
@
$
(
'.ui-slider-handle'
)
@
handle
.
qtip
@
handle
.
qtip
content
:
"
#{
Time
.
format
(
@
slider
.
slider
(
'value'
))
}
"
content
:
"
#{
Time
.
format
(
@
slider
.
slider
(
'value'
))
}
"
position
:
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
json
import
logging
import
logging
...
@@ -8,7 +11,6 @@ from django.http import Http404
...
@@ -8,7 +11,6 @@ from django.http import Http404
from
xmodule.x_module
import
XModule
from
xmodule.x_module
import
XModule
from
xmodule.raw_module
import
RawDescriptor
from
xmodule.raw_module
import
RawDescriptor
from
xmodule.contentstore.content
import
StaticContent
from
xblock.core
import
Integer
,
Scope
,
String
from
xblock.core
import
Integer
,
Scope
,
String
import
datetime
import
datetime
...
@@ -18,21 +20,26 @@ log = logging.getLogger(__name__)
...
@@ -18,21 +20,26 @@ log = logging.getLogger(__name__)
class
VideoFields
(
object
):
class
VideoFields
(
object
):
"""Fields for `VideoModule` and `VideoDescriptor`."""
data
=
String
(
help
=
"XML data for the problem"
,
scope
=
Scope
.
content
)
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
)
position
=
Integer
(
help
=
"Current position in the video"
,
scope
=
Scope
.
user_state
,
default
=
0
)
class
VideoModule
(
VideoFields
,
XModule
):
class
VideoModule
(
VideoFields
,
XModule
):
"""Video Xmodule."""
video_time
=
0
video_time
=
0
icon_class
=
'video'
icon_class
=
'video'
js
=
{
'coffee'
:
js
=
{
[
resource_string
(
__name__
,
'js/src/time.coffee'
),
'coffee'
:
[
resource_string
(
__name__
,
'js/src/video/display.coffee'
)]
+
resource_string
(
__name__
,
'js/src/time.coffee'
),
resource_string
(
__name__
,
'js/src/video/display.coffee'
)
]
+
[
resource_string
(
__name__
,
'js/src/video/display/'
+
filename
)
[
resource_string
(
__name__
,
'js/src/video/display/'
+
filename
)
for
filename
for
filename
in
sorted
(
resource_listdir
(
__name__
,
'js/src/video/display'
))
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'
)]}
css
=
{
'scss'
:
[
resource_string
(
__name__
,
'css/video/display.scss'
)]}
js_module_name
=
"Video"
js_module_name
=
"Video"
...
@@ -44,14 +51,14 @@ class VideoModule(VideoFields, XModule):
...
@@ -44,14 +51,14 @@ class VideoModule(VideoFields, XModule):
self
.
show_captions
=
xmltree
.
get
(
'show_captions'
,
'true'
)
self
.
show_captions
=
xmltree
.
get
(
'show_captions'
,
'true'
)
self
.
source
=
self
.
_get_source
(
xmltree
)
self
.
source
=
self
.
_get_source
(
xmltree
)
self
.
track
=
self
.
_get_track
(
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
):
def
_get_source
(
self
,
xmltree
):
# find the first valid source
"""Find the first valid source."""
return
self
.
_get_first_external
(
xmltree
,
'source'
)
return
self
.
_get_first_external
(
xmltree
,
'source'
)
def
_get_track
(
self
,
xmltree
):
def
_get_track
(
self
,
xmltree
):
# find the first valid track
"""Find the first valid track."""
return
self
.
_get_first_external
(
xmltree
,
'track'
)
return
self
.
_get_first_external
(
xmltree
,
'track'
)
def
_get_first_external
(
self
,
xmltree
,
tag
):
def
_get_first_external
(
self
,
xmltree
,
tag
):
...
@@ -68,59 +75,44 @@ class VideoModule(VideoFields, XModule):
...
@@ -68,59 +75,44 @@ class VideoModule(VideoFields, XModule):
break
break
return
result
return
result
def
_
get_timeframe
(
self
,
xmltree
):
def
get_timeframe
(
self
,
xmltree
):
""" Converts 'from' and 'to' parameters in video tag to seconds.
""" Converts 'from' and 'to' parameters in video tag to seconds.
If there are no parameters, returns empty string. """
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
"""Converts s in '12:34:45' format to seconds. If s is
None, returns empty string"""
None, returns empty string"""
if
s
is
None
:
if
s
tr_time
is
None
:
return
''
return
''
else
:
else
:
x
=
time
.
strptime
(
s
,
'
%
H:
%
M:
%
S'
)
obj_time
=
time
.
strptime
(
str_time
,
'
%
H:
%
M:
%
S'
)
return
datetime
.
timedelta
(
hours
=
x
.
tm_hour
,
return
datetime
.
timedelta
(
minutes
=
x
.
tm_min
,
hours
=
obj_time
.
tm_hour
,
seconds
=
x
.
tm_sec
)
.
total_seconds
()
minutes
=
obj_time
.
tm_min
,
seconds
=
obj_time
.
tm_sec
)
.
total_seconds
()
return
parse_time
(
xmltree
.
get
(
'from'
)),
parse_time
(
xmltree
.
get
(
'to'
))
return
parse_time
(
xmltree
.
get
(
'from'
)),
parse_time
(
xmltree
.
get
(
'to'
))
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
get
):
'''
"""This is not being called right now and we raise 404 error."""
Handle ajax calls to this video.
TODO (vshnayder): This is not being called right now, so the position
is not being saved.
'''
log
.
debug
(
u"GET {0}"
.
format
(
get
))
log
.
debug
(
u"GET {0}"
.
format
(
get
))
log
.
debug
(
u"DISPATCH {0}"
.
format
(
dispatch
))
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
()
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
):
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
})
return
json
.
dumps
({
'position'
:
self
.
position
})
def
video_list
(
self
):
def
video_list
(
self
):
"""Return video list."""
return
self
.
youtube
return
self
.
youtube
def
get_html
(
self
):
def
get_html
(
self
):
# We normally let JS parse this, but in the case that we need a hacked
# We normally let JS parse this, but in the case that we need a hacked
# out <object> player because YouTube has broken their <iframe> API for
# out <object> player because YouTube has broken their <iframe> API for
# the third time in a year, we need to extract it server side.
# the third time in a year, we need to extract it server side.
normal_speed_video_id
=
None
# The 1.0 speed video
normal_speed_video_id
=
None
# The 1.0 speed video
# video_list() example:
# video_list() example:
# "0.75:nugHYNiD3fI,1.0:7m8pab1MfYY,1.25:3CxdPGXShq8,1.50:F-D7bOFCnXA"
# "0.75:nugHYNiD3fI,1.0:7m8pab1MfYY,1.25:3CxdPGXShq8,1.50:F-D7bOFCnXA"
...
@@ -144,6 +136,7 @@ class VideoModule(VideoFields, XModule):
...
@@ -144,6 +136,7 @@ class VideoModule(VideoFields, XModule):
class
VideoDescriptor
(
VideoFields
,
RawDescriptor
):
class
VideoDescriptor
(
VideoFields
,
RawDescriptor
):
"""Descriptor for `VideoModule`."""
module_class
=
VideoModule
module_class
=
VideoModule
stores_state
=
True
stores_state
=
True
template_dir_name
=
"video"
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;
...
@@ -88,9 +88,10 @@ $dashboard-profile-header-color: transparent;
$dashboard-profile-color
:
rgb
(
252
,
252
,
252
);
$dashboard-profile-color
:
rgb
(
252
,
252
,
252
);
$dot-color
:
$light-gray
;
$dot-color
:
$light-gray
;
$content-wrapper-bg
:
shade
(
$body-bg
,
2%
)
;
$content-wrapper-bg
:
$white
;
$course-bg-color
:
#d6d6d6
;
$course-bg-color
:
#d6d6d6
;
$course-bg-image
:
url(../images/bg-texture.png)
;
$course-bg-image
:
url(../images/bg-texture.png)
;
$account-content-wrapper-bg
:
shade
(
$body-bg
,
2%
);
$course-profile-bg
:
rgb
(
245
,
245
,
245
);
$course-profile-bg
:
rgb
(
245
,
245
,
245
);
$course-header-bg
:
rgba
(
255
,
255
,
255
,
0
.93
);
$course-header-bg
:
rgba
(
255
,
255
,
255
,
0
.93
);
...
...
lms/static/sass/course/base/_base.scss
View file @
de1c6879
...
@@ -35,7 +35,7 @@ a {
...
@@ -35,7 +35,7 @@ a {
width
:
100%
;
width
:
100%
;
border-radius
:
3px
;
border-radius
:
3px
;
border
:
1px
solid
$outer-border-color
;
border
:
1px
solid
$outer-border-color
;
background
:
$
body
-bg
;
background
:
$
container
-bg
;
@include
box-shadow
(
0
1px
2px
rgba
(
0
,
0
,
0
,
0
.05
));
@include
box-shadow
(
0
1px
2px
rgba
(
0
,
0
,
0
,
0
.05
));
}
}
}
}
...
@@ -50,7 +50,7 @@ textarea,
...
@@ -50,7 +50,7 @@ textarea,
input
[
type
=
"text"
],
input
[
type
=
"text"
],
input
[
type
=
"email"
],
input
[
type
=
"email"
],
input
[
type
=
"password"
]
{
input
[
type
=
"password"
]
{
background
:
$
body-bg
;
background
:
$
white
;
border
:
1px
solid
$border-color-2
;
border
:
1px
solid
$border-color-2
;
@include
border-radius
(
0
);
@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
));
@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 @@
...
@@ -6,7 +6,7 @@
// page-level
// page-level
.view-register
,
.view-login
,
.view-passwordreset
{
.view-register
,
.view-login
,
.view-passwordreset
{
background
:
$
body
-bg
;
background
:
$
container
-bg
;
...
@@ -98,7 +98,7 @@
...
@@ -98,7 +98,7 @@
// layout
// layout
.content-wrapper
{
.content-wrapper
{
background
:
$content-wrapper-bg
;
background
:
$
account-
content-wrapper-bg
;
padding-bottom
:
0
;
padding-bottom
:
0
;
}
}
...
@@ -331,7 +331,7 @@
...
@@ -331,7 +331,7 @@
}
}
textarea
,
input
{
textarea
,
input
{
background
:
$
body
-bg
;
background
:
$
container
-bg
;
color
:
rgba
(
0
,
0
,
0
,.
25
);
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