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
1317e97d
Commit
1317e97d
authored
May 29, 2013
by
Giulio Gratta
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master' into feature/giulio/reset-master-stanford
parents
f53c4b44
42a55faf
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
407 additions
and
50 deletions
+407
-50
common/djangoapps/student/views.py
+2
-2
common/lib/capa/capa/tests/test_input_templates.py
+335
-26
common/lib/xmodule/xmodule/templates/videoalpha/default.yaml
+7
-3
common/lib/xmodule/xmodule/tests/test_logic.py
+33
-1
common/lib/xmodule/xmodule/videoalpha_module.py
+7
-5
lms/djangoapps/courseware/features/registration.feature
+4
-4
lms/djangoapps/courseware/features/registration.py
+11
-4
lms/urls.py
+7
-4
requirements/edx/github.txt
+1
-1
No files found.
common/djangoapps/student/views.py
View file @
1317e97d
...
@@ -527,12 +527,12 @@ def _do_create_account(post_vars):
...
@@ -527,12 +527,12 @@ def _do_create_account(post_vars):
js
=
{
'success'
:
False
}
js
=
{
'success'
:
False
}
# Figure out the cause of the integrity error
# Figure out the cause of the integrity error
if
len
(
User
.
objects
.
filter
(
username
=
post_vars
[
'username'
]))
>
0
:
if
len
(
User
.
objects
.
filter
(
username
=
post_vars
[
'username'
]))
>
0
:
js
[
'value'
]
=
"An account with th
is username
already exists."
js
[
'value'
]
=
"An account with th
e Public Username '"
+
post_vars
[
'username'
]
+
"'
already exists."
js
[
'field'
]
=
'username'
js
[
'field'
]
=
'username'
return
HttpResponse
(
json
.
dumps
(
js
))
return
HttpResponse
(
json
.
dumps
(
js
))
if
len
(
User
.
objects
.
filter
(
email
=
post_vars
[
'email'
]))
>
0
:
if
len
(
User
.
objects
.
filter
(
email
=
post_vars
[
'email'
]))
>
0
:
js
[
'value'
]
=
"An account with th
is e-mail
already exists."
js
[
'value'
]
=
"An account with th
e Email '"
+
post_vars
[
'email'
]
+
"'
already exists."
js
[
'field'
]
=
'email'
js
[
'field'
]
=
'email'
return
HttpResponse
(
json
.
dumps
(
js
))
return
HttpResponse
(
json
.
dumps
(
js
))
...
...
common/lib/capa/capa/tests/test_input_templates.py
View file @
1317e97d
"""Tests for the logic in input type mako templates."""
"""
Tests for the logic in input type mako templates.
"""
import
unittest
import
unittest
import
capa
import
capa
import
os.path
import
os.path
import
json
from
lxml
import
etree
from
lxml
import
etree
from
mako.template
import
Template
as
MakoTemplate
from
mako.template
import
Template
as
MakoTemplate
from
mako
import
exceptions
from
mako
import
exceptions
class
TemplateError
(
Exception
):
class
TemplateError
(
Exception
):
"""Error occurred while rendering a Mako template"""
"""
Error occurred while rendering a Mako template.
"""
pass
pass
class
TemplateTestCase
(
unittest
.
TestCase
):
class
TemplateTestCase
(
unittest
.
TestCase
):
"""Utilitites for testing templates"""
"""
Utilitites for testing templates.
"""
# Subclasses override this to specify the file name of the template
# Subclasses override this to specify the file name of the template
# to be loaded from capa/templates.
# to be loaded from capa/templates.
...
@@ -23,7 +30,9 @@ class TemplateTestCase(unittest.TestCase):
...
@@ -23,7 +30,9 @@ class TemplateTestCase(unittest.TestCase):
TEMPLATE_NAME
=
None
TEMPLATE_NAME
=
None
def
setUp
(
self
):
def
setUp
(
self
):
"""Load the template"""
"""
Load the template under test.
"""
capa_path
=
capa
.
__path__
[
0
]
capa_path
=
capa
.
__path__
[
0
]
self
.
template_path
=
os
.
path
.
join
(
capa_path
,
self
.
template_path
=
os
.
path
.
join
(
capa_path
,
'templates'
,
'templates'
,
...
@@ -33,18 +42,31 @@ class TemplateTestCase(unittest.TestCase):
...
@@ -33,18 +42,31 @@ class TemplateTestCase(unittest.TestCase):
template_file
.
close
()
template_file
.
close
()
def
render_to_xml
(
self
,
context_dict
):
def
render_to_xml
(
self
,
context_dict
):
"""Render the template using the `context_dict` dict.
"""
Render the template using the `context_dict` dict.
Returns an `etree` XML element."""
Returns an `etree` XML element.
"""
try
:
try
:
xml_str
=
self
.
template
.
render_unicode
(
**
context_dict
)
xml_str
=
self
.
template
.
render_unicode
(
**
context_dict
)
except
:
except
:
raise
TemplateError
(
exceptions
.
text_error_template
()
.
render
())
raise
TemplateError
(
exceptions
.
text_error_template
()
.
render
())
return
etree
.
fromstring
(
xml_str
)
# Attempt to construct an XML tree from the template
# This makes it easy to use XPath to make assertions, rather
# than dealing with a string.
# We modify the string slightly by wrapping it in <test>
# tags, to ensure it has one root element.
try
:
xml
=
etree
.
fromstring
(
"<test>"
+
xml_str
+
"</test>"
)
except
Exception
as
exc
:
raise
TemplateError
(
"Could not parse XML from '{0}': {1}"
.
format
(
xml_str
,
str
(
exc
)))
else
:
return
xml
def
assert_has_xpath
(
self
,
xml_root
,
xpath
,
context_dict
,
exact_num
=
1
):
def
assert_has_xpath
(
self
,
xml_root
,
xpath
,
context_dict
,
exact_num
=
1
):
"""Asserts that the xml tree has an element satisfying `xpath`.
"""
Asserts that the xml tree has an element satisfying `xpath`.
`xml_root` is an etree XML element
`xml_root` is an etree XML element
`xpath` is an XPath string, such as `'/foo/bar'`
`xpath` is an XPath string, such as `'/foo/bar'`
...
@@ -57,7 +79,8 @@ class TemplateTestCase(unittest.TestCase):
...
@@ -57,7 +79,8 @@ class TemplateTestCase(unittest.TestCase):
self
.
assertEqual
(
len
(
xml_root
.
xpath
(
xpath
)),
exact_num
,
msg
=
message
)
self
.
assertEqual
(
len
(
xml_root
.
xpath
(
xpath
)),
exact_num
,
msg
=
message
)
def
assert_no_xpath
(
self
,
xml_root
,
xpath
,
context_dict
):
def
assert_no_xpath
(
self
,
xml_root
,
xpath
,
context_dict
):
"""Asserts that the xml tree does NOT have an element
"""
Asserts that the xml tree does NOT have an element
satisfying `xpath`.
satisfying `xpath`.
`xml_root` is an etree XML element
`xml_root` is an etree XML element
...
@@ -67,7 +90,8 @@ class TemplateTestCase(unittest.TestCase):
...
@@ -67,7 +90,8 @@ class TemplateTestCase(unittest.TestCase):
self
.
assert_has_xpath
(
xml_root
,
xpath
,
context_dict
,
exact_num
=
0
)
self
.
assert_has_xpath
(
xml_root
,
xpath
,
context_dict
,
exact_num
=
0
)
def
assert_has_text
(
self
,
xml_root
,
xpath
,
text
,
exact
=
True
):
def
assert_has_text
(
self
,
xml_root
,
xpath
,
text
,
exact
=
True
):
"""Find the element at `xpath` in `xml_root` and assert
"""
Find the element at `xpath` in `xml_root` and assert
that its text is `text`.
that its text is `text`.
`xml_root` is an etree XML element
`xml_root` is an etree XML element
...
@@ -88,7 +112,9 @@ class TemplateTestCase(unittest.TestCase):
...
@@ -88,7 +112,9 @@ class TemplateTestCase(unittest.TestCase):
class
ChoiceGroupTemplateTest
(
TemplateTestCase
):
class
ChoiceGroupTemplateTest
(
TemplateTestCase
):
"""Test mako template for `<choicegroup>` input"""
"""
Test mako template for `<choicegroup>` input.
"""
TEMPLATE_NAME
=
'choicegroup.html'
TEMPLATE_NAME
=
'choicegroup.html'
...
@@ -103,8 +129,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
...
@@ -103,8 +129,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
super
(
ChoiceGroupTemplateTest
,
self
)
.
setUp
()
super
(
ChoiceGroupTemplateTest
,
self
)
.
setUp
()
def
test_problem_marked_correct
(
self
):
def
test_problem_marked_correct
(
self
):
"""Test conditions under which the entire problem
"""
(not a particular option) is marked correct"""
Test conditions under which the entire problem
(not a particular option) is marked correct.
"""
self
.
context
[
'status'
]
=
'correct'
self
.
context
[
'status'
]
=
'correct'
self
.
context
[
'input_type'
]
=
'checkbox'
self
.
context
[
'input_type'
]
=
'checkbox'
...
@@ -123,8 +151,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
...
@@ -123,8 +151,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
self
.
context
)
self
.
context
)
def
test_problem_marked_incorrect
(
self
):
def
test_problem_marked_incorrect
(
self
):
"""Test all conditions under which the entire problem
"""
(not a particular option) is marked incorrect"""
Test all conditions under which the entire problem
(not a particular option) is marked incorrect.
"""
conditions
=
[
conditions
=
[
{
'status'
:
'incorrect'
,
'input_type'
:
'radio'
,
'value'
:
''
},
{
'status'
:
'incorrect'
,
'input_type'
:
'radio'
,
'value'
:
''
},
{
'status'
:
'incorrect'
,
'input_type'
:
'checkbox'
,
'value'
:
[]},
{
'status'
:
'incorrect'
,
'input_type'
:
'checkbox'
,
'value'
:
[]},
...
@@ -151,8 +181,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
...
@@ -151,8 +181,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
self
.
context
)
self
.
context
)
def
test_problem_marked_unsubmitted
(
self
):
def
test_problem_marked_unsubmitted
(
self
):
"""Test all conditions under which the entire problem
"""
(not a particular option) is marked unanswered"""
Test all conditions under which the entire problem
(not a particular option) is marked unanswered.
"""
conditions
=
[
conditions
=
[
{
'status'
:
'unsubmitted'
,
'input_type'
:
'radio'
,
'value'
:
''
},
{
'status'
:
'unsubmitted'
,
'input_type'
:
'radio'
,
'value'
:
''
},
{
'status'
:
'unsubmitted'
,
'input_type'
:
'radio'
,
'value'
:
[]},
{
'status'
:
'unsubmitted'
,
'input_type'
:
'radio'
,
'value'
:
[]},
...
@@ -181,8 +213,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
...
@@ -181,8 +213,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
self
.
context
)
self
.
context
)
def
test_option_marked_correct
(
self
):
def
test_option_marked_correct
(
self
):
"""Test conditions under which a particular option
"""
(not the entire problem) is marked correct."""
Test conditions under which a particular option
(not the entire problem) is marked correct.
"""
conditions
=
[
conditions
=
[
{
'input_type'
:
'radio'
,
'value'
:
'2'
},
{
'input_type'
:
'radio'
,
'value'
:
'2'
},
{
'input_type'
:
'radio'
,
'value'
:
[
'2'
]}]
{
'input_type'
:
'radio'
,
'value'
:
[
'2'
]}]
...
@@ -200,8 +234,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
...
@@ -200,8 +234,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
self
.
assert_no_xpath
(
xml
,
xpath
,
self
.
context
)
self
.
assert_no_xpath
(
xml
,
xpath
,
self
.
context
)
def
test_option_marked_incorrect
(
self
):
def
test_option_marked_incorrect
(
self
):
"""Test conditions under which a particular option
"""
(not the entire problem) is marked incorrect."""
Test conditions under which a particular option
(not the entire problem) is marked incorrect.
"""
conditions
=
[
conditions
=
[
{
'input_type'
:
'radio'
,
'value'
:
'2'
},
{
'input_type'
:
'radio'
,
'value'
:
'2'
},
{
'input_type'
:
'radio'
,
'value'
:
[
'2'
]}]
{
'input_type'
:
'radio'
,
'value'
:
[
'2'
]}]
...
@@ -219,7 +255,8 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
...
@@ -219,7 +255,8 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
self
.
assert_no_xpath
(
xml
,
xpath
,
self
.
context
)
self
.
assert_no_xpath
(
xml
,
xpath
,
self
.
context
)
def
test_never_show_correctness
(
self
):
def
test_never_show_correctness
(
self
):
"""Test conditions under which we tell the template to
"""
Test conditions under which we tell the template to
NOT show correct/incorrect, but instead show a message.
NOT show correct/incorrect, but instead show a message.
This is used, for example, by the Justice course to ask
This is used, for example, by the Justice course to ask
...
@@ -268,8 +305,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
...
@@ -268,8 +305,10 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
self
.
context
[
'submitted_message'
])
self
.
context
[
'submitted_message'
])
def
test_no_message_before_submission
(
self
):
def
test_no_message_before_submission
(
self
):
"""Ensure that we don't show the `submitted_message`
"""
before submitting"""
Ensure that we don't show the `submitted_message`
before submitting.
"""
conditions
=
[
conditions
=
[
{
'input_type'
:
'radio'
,
'status'
:
'unsubmitted'
,
'value'
:
''
},
{
'input_type'
:
'radio'
,
'status'
:
'unsubmitted'
,
'value'
:
''
},
...
@@ -298,7 +337,9 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
...
@@ -298,7 +337,9 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
class
TextlineTemplateTest
(
TemplateTestCase
):
class
TextlineTemplateTest
(
TemplateTestCase
):
"""Test mako template for `<textline>` input"""
"""
Test mako template for `<textline>` input.
"""
TEMPLATE_NAME
=
'textline.html'
TEMPLATE_NAME
=
'textline.html'
...
@@ -405,3 +446,271 @@ class TextlineTemplateTest(TemplateTestCase):
...
@@ -405,3 +446,271 @@ class TextlineTemplateTest(TemplateTestCase):
xpath
=
"//span[@class='message']"
xpath
=
"//span[@class='message']"
self
.
assert_has_text
(
xml
,
xpath
,
self
.
context
[
'msg'
])
self
.
assert_has_text
(
xml
,
xpath
,
self
.
context
[
'msg'
])
class
AnnotationInputTemplateTest
(
TemplateTestCase
):
"""
Test mako template for `<annotationinput>` input.
"""
TEMPLATE_NAME
=
'annotationinput.html'
def
setUp
(
self
):
self
.
context
=
{
'id'
:
2
,
'value'
:
'<p>Test value</p>'
,
'title'
:
'<h1>This is a title</h1>'
,
'text'
:
'<p><b>This</b> is a test.</p>'
,
'comment'
:
'<p>This is a test comment</p>'
,
'comment_prompt'
:
'<p>This is a test comment prompt</p>'
,
'comment_value'
:
'<p>This is the value of a test comment</p>'
,
'tag_prompt'
:
'<p>This is a tag prompt</p>'
,
'options'
:
[],
'has_options_value'
:
False
,
'debug'
:
False
,
'status'
:
'unsubmitted'
,
'return_to_annotation'
:
False
,
'msg'
:
'<p>This is a test message</p>'
,
}
super
(
AnnotationInputTemplateTest
,
self
)
.
setUp
()
def
test_return_to_annotation
(
self
):
"""
Test link for `Return to Annotation` appears if and only if
the flag is set.
"""
xpath
=
"//a[@class='annotation-return']"
# If return_to_annotation set, then show the link
self
.
context
[
'return_to_annotation'
]
=
True
xml
=
self
.
render_to_xml
(
self
.
context
)
self
.
assert_has_xpath
(
xml
,
xpath
,
self
.
context
)
# Otherwise, do not show the links
self
.
context
[
'return_to_annotation'
]
=
False
xml
=
self
.
render_to_xml
(
self
.
context
)
self
.
assert_no_xpath
(
xml
,
xpath
,
self
.
context
)
def
test_option_selection
(
self
):
"""
Test that selected options are selected.
"""
# Create options 0-4 and select option 2
self
.
context
[
'options_value'
]
=
[
2
]
self
.
context
[
'options'
]
=
[
{
'id'
:
id_num
,
'choice'
:
'correct'
,
'description'
:
'<p>Unescaped <b>HTML {0}</b></p>'
.
format
(
id_num
)}
for
id_num
in
range
(
0
,
5
)]
xml
=
self
.
render_to_xml
(
self
.
context
)
# Expect that each option description is visible
# with unescaped HTML.
# Since the HTML is unescaped, we can traverse the XML tree
for
id_num
in
range
(
0
,
5
):
xpath
=
"//span[@data-id='{0}']/p/b"
.
format
(
id_num
)
self
.
assert_has_text
(
xml
,
xpath
,
'HTML {0}'
.
format
(
id_num
),
exact
=
False
)
# Expect that the correct option is selected
xpath
=
"//span[contains(@class,'selected')]/p/b"
self
.
assert_has_text
(
xml
,
xpath
,
'HTML 2'
,
exact
=
False
)
def
test_submission_status
(
self
):
"""
Test that the submission status displays correctly.
"""
# Test cases of `(input_status, expected_css_class)` tuples
test_cases
=
[(
'unsubmitted'
,
'unanswered'
),
(
'incomplete'
,
'incorrect'
),
(
'incorrect'
,
'incorrect'
)]
for
(
input_status
,
expected_css_class
)
in
test_cases
:
self
.
context
[
'status'
]
=
input_status
xml
=
self
.
render_to_xml
(
self
.
context
)
xpath
=
"//span[@class='{0}']"
.
format
(
expected_css_class
)
self
.
assert_has_xpath
(
xml
,
xpath
,
self
.
context
)
# If individual options are being marked, then expect
# just the option to be marked incorrect, not the whole problem
self
.
context
[
'has_options_value'
]
=
True
self
.
context
[
'status'
]
=
'incorrect'
xpath
=
"//span[@class='incorrect']"
xml
=
self
.
render_to_xml
(
self
.
context
)
self
.
assert_no_xpath
(
xml
,
xpath
,
self
.
context
)
def
test_display_html_comment
(
self
):
"""
Test that HTML comment and comment prompt render.
"""
self
.
context
[
'comment'
]
=
"<p>Unescaped <b>comment HTML</b></p>"
self
.
context
[
'comment_prompt'
]
=
"<p>Prompt <b>prompt HTML</b></p>"
self
.
context
[
'text'
]
=
"<p>Unescaped <b>text</b></p>"
xml
=
self
.
render_to_xml
(
self
.
context
)
# Because the HTML is unescaped, we should be able to
# descend to the <b> tag
xpath
=
"//div[@class='block']/p/b"
self
.
assert_has_text
(
xml
,
xpath
,
'prompt HTML'
)
xpath
=
"//div[@class='block block-comment']/p/b"
self
.
assert_has_text
(
xml
,
xpath
,
'comment HTML'
)
xpath
=
"//div[@class='block block-highlight']/p/b"
self
.
assert_has_text
(
xml
,
xpath
,
'text'
)
def
test_display_html_tag_prompt
(
self
):
"""
Test that HTML tag prompts render.
"""
self
.
context
[
'tag_prompt'
]
=
"<p>Unescaped <b>HTML</b></p>"
xml
=
self
.
render_to_xml
(
self
.
context
)
# Because the HTML is unescaped, we should be able to
# descend to the <b> tag
xpath
=
"//div[@class='block']/p/b"
self
.
assert_has_text
(
xml
,
xpath
,
'HTML'
)
class
MathStringTemplateTest
(
TemplateTestCase
):
"""
Test mako template for `<mathstring>` input.
"""
TEMPLATE_NAME
=
'mathstring.html'
def
setUp
(
self
):
self
.
context
=
{
'isinline'
:
False
,
'mathstr'
:
''
,
'tail'
:
''
}
super
(
MathStringTemplateTest
,
self
)
.
setUp
()
def
test_math_string_inline
(
self
):
self
.
context
[
'isinline'
]
=
True
self
.
context
[
'mathstr'
]
=
'y = ax^2 + bx + c'
xml
=
self
.
render_to_xml
(
self
.
context
)
xpath
=
"//section[@class='math-string']/span[1]"
self
.
assert_has_text
(
xml
,
xpath
,
'[mathjaxinline]y = ax^2 + bx + c[/mathjaxinline]'
)
def
test_math_string_not_inline
(
self
):
self
.
context
[
'isinline'
]
=
False
self
.
context
[
'mathstr'
]
=
'y = ax^2 + bx + c'
xml
=
self
.
render_to_xml
(
self
.
context
)
xpath
=
"//section[@class='math-string']/span[1]"
self
.
assert_has_text
(
xml
,
xpath
,
'[mathjax]y = ax^2 + bx + c[/mathjax]'
)
def
test_tail_html
(
self
):
self
.
context
[
'tail'
]
=
"<p>This is some <b>tail</b> <em>HTML</em></p>"
xml
=
self
.
render_to_xml
(
self
.
context
)
# HTML from `tail` should NOT be escaped.
# We should be able to traverse it as part of the XML tree
xpath
=
"//section[@class='math-string']/span[2]/p/b"
self
.
assert_has_text
(
xml
,
xpath
,
'tail'
)
xpath
=
"//section[@class='math-string']/span[2]/p/em"
self
.
assert_has_text
(
xml
,
xpath
,
'HTML'
)
class
OptionInputTemplateTest
(
TemplateTestCase
):
"""
Test mako template for `<optioninput>` input.
"""
TEMPLATE_NAME
=
'optioninput.html'
def
setUp
(
self
):
self
.
context
=
{
'id'
:
2
,
'options'
:
[],
'status'
:
'unsubmitted'
,
'value'
:
0
}
super
(
OptionInputTemplateTest
,
self
)
.
setUp
()
def
test_select_options
(
self
):
# Create options 0-4, and select option 2
self
.
context
[
'options'
]
=
[(
id_num
,
'<b>Option {0}</b>'
.
format
(
id_num
))
for
id_num
in
range
(
0
,
5
)]
self
.
context
[
'value'
]
=
2
xml
=
self
.
render_to_xml
(
self
.
context
)
# Should have a dummy default
xpath
=
"//option[@value='option_2_dummy_default']"
self
.
assert_has_xpath
(
xml
,
xpath
,
self
.
context
)
# Should have each of the options, with the correct description
# The description HTML should NOT be escaped
# (that's why we descend into the <b> tag)
for
id_num
in
range
(
0
,
5
):
xpath
=
"//option[@value='{0}']/b"
.
format
(
id_num
)
self
.
assert_has_text
(
xml
,
xpath
,
'Option {0}'
.
format
(
id_num
))
# Should have the correct option selected
xpath
=
"//option[@selected='true']/b"
self
.
assert_has_text
(
xml
,
xpath
,
'Option 2'
)
def
test_status
(
self
):
# Test cases, where each tuple represents
# `(input_status, expected_css_class)`
test_cases
=
[(
'unsubmitted'
,
'unanswered'
),
(
'correct'
,
'correct'
),
(
'incorrect'
,
'incorrect'
),
(
'incomplete'
,
'incorrect'
)]
for
(
input_status
,
expected_css_class
)
in
test_cases
:
self
.
context
[
'status'
]
=
input_status
xml
=
self
.
render_to_xml
(
self
.
context
)
xpath
=
"//span[@class='{0}']"
.
format
(
expected_css_class
)
self
.
assert_has_xpath
(
xml
,
xpath
,
self
.
context
)
class
DragAndDropTemplateTest
(
TemplateTestCase
):
"""
Test mako template for `<draganddropinput>` input.
"""
TEMPLATE_NAME
=
'drag_and_drop_input.html'
def
setUp
(
self
):
self
.
context
=
{
'id'
:
2
,
'drag_and_drop_json'
:
''
,
'value'
:
0
,
'status'
:
'unsubmitted'
,
'msg'
:
''
}
super
(
DragAndDropTemplateTest
,
self
)
.
setUp
()
def
test_status
(
self
):
# Test cases, where each tuple represents
# `(input_status, expected_css_class, expected_text)`
test_cases
=
[(
'unsubmitted'
,
'unanswered'
,
'unanswered'
),
(
'correct'
,
'correct'
,
'correct'
),
(
'incorrect'
,
'incorrect'
,
'incorrect'
),
(
'incomplete'
,
'incorrect'
,
'incomplete'
)]
for
(
input_status
,
expected_css_class
,
expected_text
)
in
test_cases
:
self
.
context
[
'status'
]
=
input_status
xml
=
self
.
render_to_xml
(
self
.
context
)
# Expect a <div> with the status
xpath
=
"//div[@class='{0}']"
.
format
(
expected_css_class
)
self
.
assert_has_xpath
(
xml
,
xpath
,
self
.
context
)
# Expect a <p> with the status
xpath
=
"//p[@class='status']"
self
.
assert_has_text
(
xml
,
xpath
,
expected_text
,
exact
=
False
)
def
test_drag_and_drop_json_html
(
self
):
json_with_html
=
json
.
dumps
({
'test'
:
'<p>Unescaped <b>HTML</b></p>'
})
self
.
context
[
'drag_and_drop_json'
]
=
json_with_html
xml
=
self
.
render_to_xml
(
self
.
context
)
# Assert that the JSON-encoded string was inserted without
# escaping the HTML. We should be able to traverse the XML tree.
xpath
=
"//div[@class='drag_and_drop_problem_json']/p/b"
self
.
assert_has_text
(
xml
,
xpath
,
'HTML'
)
common/lib/xmodule/xmodule/templates/videoalpha/default.yaml
View file @
1317e97d
---
---
metadata
:
metadata
:
display_name
:
default
display_name
:
Video Alpha 1
data_dir
:
a_made_up_name
version
:
1
data
:
|
data
:
|
<videoalpha youtube="0.75:JMD_ifUUfsU,1.0:OEoXaMPEzfM,1.25:AKqURZnYqpk,1.50:DYpADpL7jAY"/>
<videoalpha show_captions="true" sub="name_of_file" youtube="0.75:JMD_ifUUfsU,1.0:OEoXaMPEzfM,1.25:AKqURZnYqpk,1.50:DYpADpL7jAY" >
<source src="https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.mp4"/>
<source src="https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.webm"/>
<source src="https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.ogv"/>
</videoalpha>
children
:
[]
children
:
[]
common/lib/xmodule/xmodule/tests/test_logic.py
View file @
1317e97d
...
@@ -4,10 +4,12 @@
...
@@ -4,10 +4,12 @@
import
json
import
json
import
unittest
import
unittest
from
lxml
import
etree
from
xmodule.poll_module
import
PollDescriptor
from
xmodule.poll_module
import
PollDescriptor
from
xmodule.conditional_module
import
ConditionalDescriptor
from
xmodule.conditional_module
import
ConditionalDescriptor
from
xmodule.word_cloud_module
import
WordCloudDescriptor
from
xmodule.word_cloud_module
import
WordCloudDescriptor
from
xmodule.videoalpha_module
import
VideoAlphaDescriptor
class
PostData
:
class
PostData
:
"""Class which emulate postdata."""
"""Class which emulate postdata."""
...
@@ -117,3 +119,33 @@ class WordCloudModuleTest(LogicTest):
...
@@ -117,3 +119,33 @@ class WordCloudModuleTest(LogicTest):
)
)
self
.
assertEqual
(
100.0
,
sum
(
i
[
'percent'
]
for
i
in
response
[
'top_words'
])
)
self
.
assertEqual
(
100.0
,
sum
(
i
[
'percent'
]
for
i
in
response
[
'top_words'
])
)
class
VideoAlphaModuleTest
(
LogicTest
):
descriptor_class
=
VideoAlphaDescriptor
raw_model_data
=
{
'data'
:
'<videoalpha />'
}
def
test_get_timeframe_no_parameters
(
self
):
xmltree
=
etree
.
fromstring
(
'<videoalpha>test</videoalpha>'
)
output
=
self
.
xmodule
.
_get_timeframe
(
xmltree
)
self
.
assertEqual
(
output
,
(
''
,
''
))
def
test_get_timeframe_with_one_parameter
(
self
):
xmltree
=
etree
.
fromstring
(
'<videoalpha start_time="00:04:07">test</videoalpha>'
)
output
=
self
.
xmodule
.
_get_timeframe
(
xmltree
)
self
.
assertEqual
(
output
,
(
247
,
''
))
def
test_get_timeframe_with_two_parameters
(
self
):
xmltree
=
etree
.
fromstring
(
'''<videoalpha
start_time="00:04:07"
end_time="13:04:39"
>test</videoalpha>'''
)
output
=
self
.
xmodule
.
_get_timeframe
(
xmltree
)
self
.
assertEqual
(
output
,
(
247
,
47079
))
common/lib/xmodule/xmodule/videoalpha_module.py
View file @
1317e97d
...
@@ -93,7 +93,7 @@ class VideoAlphaModule(VideoAlphaFields, XModule):
...
@@ -93,7 +93,7 @@ class VideoAlphaModule(VideoAlphaFields, XModule):
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 '
start_time' and 'end_time
' 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
):
...
@@ -103,11 +103,13 @@ class VideoAlphaModule(VideoAlphaFields, XModule):
...
@@ -103,11 +103,13 @@ class VideoAlphaModule(VideoAlphaFields, XModule):
return
''
return
''
else
:
else
:
x
=
time
.
strptime
(
s
,
'
%
H:
%
M:
%
S'
)
x
=
time
.
strptime
(
s
,
'
%
H:
%
M:
%
S'
)
return
datetime
.
timedelta
(
hours
=
x
.
tm_hour
,
return
datetime
.
timedelta
(
minutes
=
x
.
tm_min
,
hours
=
x
.
tm_hour
,
seconds
=
x
.
tm_sec
)
.
total_seconds
()
minutes
=
x
.
tm_min
,
seconds
=
x
.
tm_sec
)
.
total_seconds
()
return
parse_time
(
xmltree
.
get
(
'
from'
)),
parse_time
(
xmltree
.
get
(
'to
'
))
return
parse_time
(
xmltree
.
get
(
'
start_time'
)),
parse_time
(
xmltree
.
get
(
'end_time
'
))
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
get
):
"""Handle ajax calls to this video.
"""Handle ajax calls to this video.
...
...
lms/djangoapps/courseware/features/registration.feature
View file @
1317e97d
...
@@ -13,8 +13,8 @@ Feature: Register for a course
...
@@ -13,8 +13,8 @@ Feature: Register for a course
Scenario
:
I
can unregister for a course
Scenario
:
I
can unregister for a course
Given
I am registered for the course
"6.002x"
Given
I am registered for the course
"6.002x"
And
I visit the dashboard
And
I visit the dashboard
When
I click the link with the text
"Unregister"
Then
I should see the course numbered
"6.002x"
in my dashboard
And
I press the
"Unregister"
button in the Unenroll dialog
When
I unregister for the course numbered
"6.002x"
Then
All dialogs should be closed
Then
I should be on the dashboard page
And
I should be on the dashboard page
And
I should see
"Looks like you haven't registered for any courses yet."
somewhere in the page
And
I should see
"Looks like you haven't registered for any courses yet."
somewhere in the page
And
I should NOT see the course numbered
"6.002x"
in my dashboard
lms/djangoapps/courseware/features/registration.py
View file @
1317e97d
...
@@ -25,8 +25,15 @@ def i_should_see_that_course_in_my_dashboard(step, course):
...
@@ -25,8 +25,15 @@ def i_should_see_that_course_in_my_dashboard(step, course):
assert
world
.
is_css_present
(
course_link_css
)
assert
world
.
is_css_present
(
course_link_css
)
@step
(
u'I press the "([^"]*)" button in the Unenroll dialog'
)
@step
(
u'I should NOT see the course numbered "([^"]*)" in my dashboard$'
)
def
i_press_the_button_in_the_unenroll_dialog
(
step
,
value
):
def
i_should_not_see_that_course_in_my_dashboard
(
step
,
course
):
button_css
=
'section#unenroll-modal input[value="
%
s"]'
%
value
course_link_css
=
'section.my-courses a[href*="
%
s"]'
%
course
assert
not
world
.
is_css_present
(
course_link_css
)
@step
(
u'I unregister for the course numbered "([^"]*)"'
)
def
i_unregister_for_that_course
(
step
,
course
):
unregister_css
=
'section.info a[href*="#unenroll-modal"][data-course-number*="
%
s"]'
%
course
world
.
css_click
(
unregister_css
)
button_css
=
'section#unenroll-modal input[value="Unregister"]'
world
.
css_click
(
button_css
)
world
.
css_click
(
button_css
)
assert
world
.
is_css_present
(
'section.container.dashboard'
)
lms/urls.py
View file @
1317e97d
...
@@ -22,10 +22,6 @@ urlpatterns = ('', # nopep8
...
@@ -22,10 +22,6 @@ urlpatterns = ('', # nopep8
url
(
r'^admin_dashboard$'
,
'dashboard.views.dashboard'
),
url
(
r'^admin_dashboard$'
,
'dashboard.views.dashboard'
),
# Adding to allow debugging issues when prod is mysteriously different from staging
# (specifically missing get parameters in certain cases)
url
(
r'^debug_request$'
,
'util.views.debug_request'
),
url
(
r'^change_email$'
,
'student.views.change_email_request'
,
name
=
"change_email"
),
url
(
r'^change_email$'
,
'student.views.change_email_request'
,
name
=
"change_email"
),
url
(
r'^email_confirm/(?P<key>[^/]*)$'
,
'student.views.confirm_email_change'
),
url
(
r'^email_confirm/(?P<key>[^/]*)$'
,
'student.views.confirm_email_change'
),
url
(
r'^change_name$'
,
'student.views.change_name_request'
,
name
=
"change_name"
),
url
(
r'^change_name$'
,
'student.views.change_name_request'
,
name
=
"change_name"
),
...
@@ -334,6 +330,13 @@ if settings.DEBUG or settings.MITX_FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'):
...
@@ -334,6 +330,13 @@ if settings.DEBUG or settings.MITX_FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'):
## Jasmine and admin
## Jasmine and admin
urlpatterns
+=
(
url
(
r'^admin/'
,
include
(
admin
.
site
.
urls
)),)
urlpatterns
+=
(
url
(
r'^admin/'
,
include
(
admin
.
site
.
urls
)),)
if
settings
.
DEBUG
:
# Originally added to allow debugging issues when prod is
# mysteriously different from staging (specifically missing get
# parameters in certain cases), but removing from prod because
# it's a security risk.
urlpatterns
+=
(
url
(
r'^debug_request$'
,
'util.views.debug_request'
),)
if
settings
.
MITX_FEATURES
.
get
(
'AUTH_USE_OPENID'
):
if
settings
.
MITX_FEATURES
.
get
(
'AUTH_USE_OPENID'
):
urlpatterns
+=
(
urlpatterns
+=
(
url
(
r'^openid/login/$'
,
'django_openid_auth.views.login_begin'
,
name
=
'openid-login'
),
url
(
r'^openid/login/$'
,
'django_openid_auth.views.login_begin'
,
name
=
'openid-login'
),
...
...
requirements/edx/github.txt
View file @
1317e97d
...
@@ -9,4 +9,4 @@
...
@@ -9,4 +9,4 @@
# Our libraries:
# Our libraries:
-e git+https://github.com/edx/XBlock.git@2144a25d#egg=XBlock
-e git+https://github.com/edx/XBlock.git@2144a25d#egg=XBlock
-e git+https://github.com/edx/codejail.git@
72cf791
#egg=codejail
-e git+https://github.com/edx/codejail.git@
874361f
#egg=codejail
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