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
6ff762b6
Commit
6ff762b6
authored
Sep 19, 2016
by
muhammad-ammar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
allow html inside label and descriptions
TNL-5557
parent
2b80c619
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
259 additions
and
138 deletions
+259
-138
common/lib/capa/capa/capa_problem.py
+9
-13
common/lib/capa/capa/inputtypes.py
+2
-2
common/lib/capa/capa/templates/chemicalequationinput.html
+2
-1
common/lib/capa/capa/templates/choicegroup.html
+4
-3
common/lib/capa/capa/templates/choicetext.html
+2
-1
common/lib/capa/capa/templates/formulaequationinput.html
+1
-1
common/lib/capa/capa/templates/optioninput.html
+2
-1
common/lib/capa/capa/templates/schematicinput.html
+2
-1
common/lib/capa/capa/templates/textline.html
+1
-1
common/lib/capa/capa/tests/test_capa_problem.py
+47
-50
common/lib/capa/capa/tests/test_html_render.py
+1
-1
common/lib/capa/capa/tests/test_input_templates.py
+136
-36
common/lib/capa/capa/tests/test_inputtypes.py
+27
-26
common/lib/capa/capa/tests/test_util.py
+10
-1
common/lib/capa/capa/util.py
+13
-0
No files found.
common/lib/capa/capa/capa_problem.py
View file @
6ff762b6
...
...
@@ -31,6 +31,8 @@ import capa.responsetypes as responsetypes
from
capa.util
import
contextualize_text
,
convert_files_to_filenames
import
capa.xqueue_interface
as
xqueue_interface
from
capa.safe_exec
import
safe_exec
from
openedx.core.djangolib.markup
import
HTML
from
xmodule.stringify
import
stringify_children
# extra things displayed after "show answers" is pressed
...
...
@@ -926,7 +928,7 @@ class LoncapaProblem(object):
group_label_tag
.
tag
=
'p'
group_label_tag
.
set
(
'id'
,
responsetype_id
)
group_label_tag
.
set
(
'class'
,
'multi-inputs-group-label'
)
group_label_tag_text
=
group_label_tag
.
text
group_label_tag_text
=
stringify_children
(
group_label_tag
)
for
inputfield
in
inputfields
:
problem_data
[
inputfield
.
get
(
'id'
)]
=
{
...
...
@@ -938,7 +940,7 @@ class LoncapaProblem(object):
# Extract label value from <label> tag or label attribute from inside the responsetype
responsetype_label_tag
=
response
.
find
(
'label'
)
if
responsetype_label_tag
is
not
None
:
label
=
responsetype_label_tag
.
text
label
=
stringify_children
(
responsetype_label_tag
)
# store <label> tag containing question text to delete
# it later otherwise question will be rendered twice
element_to_be_deleted
=
responsetype_label_tag
...
...
@@ -950,21 +952,15 @@ class LoncapaProblem(object):
p_tag
=
response
.
xpath
(
'preceding-sibling::*[1][self::p]'
)
if
p_tag
and
p_tag
[
0
]
.
text
==
inputfields
[
0
]
.
attrib
[
'label'
]:
label
=
p_tag
[
0
]
.
text
p_tag_children
=
list
(
p_tag
[
0
])
if
len
(
p_tag_children
)
==
0
:
element_to_be_deleted
=
p_tag
[
0
]
else
:
# Delete the text from the p-tag, but leave the children.
p_tag
[
0
]
.
text
=
''
label
=
stringify_children
(
p_tag
[
0
])
element_to_be_deleted
=
p_tag
[
0
]
else
:
# In this case the problems don't have tag or label attribute inside the responsetype
# so we will get the first preceding label tag w.r.t to this responsetype.
# This will take care of those multi-question problems that are not using --- in their markdown.
label_tag
=
response
.
xpath
(
'preceding-sibling::*[1][self::label]'
)
if
label_tag
:
label
=
label_tag
[
0
]
.
text
label
=
stringify_children
(
label_tag
[
0
])
element_to_be_deleted
=
label_tag
[
0
]
# delete label or p element only if inputtype is fully accessible
...
...
@@ -978,11 +974,11 @@ class LoncapaProblem(object):
for
description
in
description_tags
:
descriptions
[
"description_
%
s_
%
i"
%
(
responsetype_id
,
description_id
)
]
=
description
.
text
]
=
HTML
(
stringify_children
(
description
))
response
.
remove
(
description
)
description_id
+=
1
problem_data
[
inputfields
[
0
]
.
get
(
'id'
)]
=
{
'label'
:
label
.
strip
(
)
if
label
else
''
,
'label'
:
HTML
(
label
.
strip
()
)
if
label
else
''
,
'descriptions'
:
descriptions
}
common/lib/capa/capa/inputtypes.py
View file @
6ff762b6
...
...
@@ -322,14 +322,14 @@ class InputTypeBase(object):
'msg'
:
self
.
msg
,
'response_data'
:
self
.
response_data
,
'STATIC_URL'
:
self
.
capa_system
.
STATIC_URL
,
'describedby'
:
''
,
'describedby
_html
'
:
''
,
}
# Don't add aria-describedby attribute if there are no descriptions
if
self
.
response_data
.
get
(
'descriptions'
):
description_ids
=
' '
.
join
(
self
.
response_data
.
get
(
'descriptions'
)
.
keys
())
context
.
update
(
{
'describedby'
:
'aria-describedby="{}"'
.
format
(
description_ids
)}
{
'describedby
_html
'
:
'aria-describedby="{}"'
.
format
(
description_ids
)}
)
context
.
update
(
...
...
common/lib/capa/capa/templates/chemicalequationinput.html
View file @
6ff762b6
<
%!
from
capa
.
util
import
remove_markup
%
>
<div
id=
"chemicalequationinput_${id}"
class=
"chemicalequationinput"
>
<div
class=
"script_placeholder"
data-src=
"${previewer}"
/>
<div
class=
"${status.classname}"
id=
"status_${id}"
>
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
aria-label=
"${re
sponse_data['label']
}"
aria-describedby=
"answer_${id}"
data-input-id=
"${id}"
value=
"${value|h}"
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
aria-label=
"${re
move_markup(response_data['label'])
}"
aria-describedby=
"answer_${id}"
data-input-id=
"${id}"
value=
"${value|h}"
%
if
size:
size=
"${size}"
%
endif
...
...
common/lib/capa/capa/templates/choicegroup.html
View file @
6ff762b6
<
%
page
expression_filter=
"h"
/>
<
%!
from
openedx
.
core
.
djangolib
.
markup
import
HTML
%
>
<
%
def
is_radio_input
(
choice_id
)
:
...
...
@@ -6,7 +7,7 @@
))
%
>
<form
class=
"choicegroup capa_inputtype"
id=
"inputtype_${id}"
>
<fieldset
${
describedby
}
>
<fieldset
${
HTML
(
describedby_html
)
}
>
% if response_data['label']:
<legend
id=
"${id}-legend"
class=
"response-fieldset-legend field-group-hd"
>
${response_data['label']}
</legend>
% endif
...
...
@@ -36,7 +37,7 @@
% endif
% endif
class="${label_class}"
${
describedby
}
${
HTML(describedby_html)
}
>
<input
type=
"${input_type}"
name=
"input_${id}${name_array_suffix}"
id=
"input_${id}_${choice_id}"
class=
"field-input input-${input_type}"
value=
"${choice_id}"
##
If
the
student
selected
this
choice
...
...
...
@@ -45,7 +46,7 @@
%
elif
input_type
!=
'
radio
'
and
choice_id
in
value:
checked=
"true"
%
endif
/>
${
choice_label
}
/>
${
HTML(choice_label)
}
% if is_radio_input(choice_id):
% if status in ('correct', 'partially-correct', 'incorrect') and not show_correctness == 'never':
...
...
common/lib/capa/capa/templates/choicetext.html
View file @
6ff762b6
<
%!
from
capa
.
util
import
remove_markup
%
>
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
%
>
<
%
element_checked =
False
%
>
% for choice_id, _ in choices:
...
...
@@ -10,7 +11,7 @@
<form
class=
"choicetextgroup capa_inputtype"
id=
"inputtype_${id}"
>
<div
class=
"script_placeholder"
data-src=
"${STATIC_URL}js/capa/choicetextinput.js"
/>
<fieldset
aria-label=
"${re
sponse_data['label']
}"
>
<fieldset
aria-label=
"${re
move_markup(response_data['label'])
}"
>
% for choice_id, choice_description in choices:
<
%
choice_id =
choice_id
%
>
<section
id=
"forinput${choice_id}"
...
...
common/lib/capa/capa/templates/formulaequationinput.html
View file @
6ff762b6
...
...
@@ -11,7 +11,7 @@
% endfor
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
data-input-id=
"${id}"
value=
"${value}"
${
describedby
|
n
,
decode
.
utf8
}
${
HTML
(
describedby_html
)
}
%
if
size:
size=
"${size}"
%
endif
...
...
common/lib/capa/capa/templates/optioninput.html
View file @
6ff762b6
<
%
page
expression_filter=
"h"
/>
<
%!
from
openedx
.
core
.
djangolib
.
markup
import
HTML
%
>
<
%
doinline =
"inline"
if
inline
else
""
%
>
...
...
@@ -10,7 +11,7 @@
<p
class=
"question-description"
id=
"${description_id}"
>
${description_text}
</p>
% endfor
<select
name=
"input_${id}"
id=
"input_${id}"
${
describedby
}
>
<select
name=
"input_${id}"
id=
"input_${id}"
${
HTML
(
describedby_html
)
}
>
<option
value=
"option_${id}_dummy_default"
>
${default_option_text}
</option>
% for option_id, option_description in options:
<option
value=
"${option_id}"
...
...
common/lib/capa/capa/templates/schematicinput.html
View file @
6ff762b6
<
%!
from
capa
.
util
import
remove_markup
%
>
<div>
<div
class=
"script_placeholder"
data-src=
"${setup_script}"
/>
<input
type=
"hidden"
...
...
@@ -8,7 +9,7 @@
analyses=
"${analyses}"
name=
"input_${id}"
id=
"input_${id}"
aria-label=
"${re
sponse_data['label']
}"
aria-label=
"${re
move_markup(response_data['label'])
}"
aria-describedby=
"answer_${id}"
value=
"${value|h}"
initial_value=
"${initial_value|h}"
...
...
common/lib/capa/capa/templates/textline.html
View file @
6ff762b6
...
...
@@ -23,7 +23,7 @@
% for description_id, description_text in response_data['descriptions'].items():
<p
class=
"question-description"
id=
"${description_id}"
>
${description_text}
</p>
% endfor
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
${
describedby
|
n
,
decode
.
utf8
}
value=
"${value}"
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
${
HTML
(
describedby_html
)
}
value=
"${value}"
%
if
do_math:
class=
"math"
%
endif
...
...
common/lib/capa/capa/tests/test_capa_problem.py
View file @
6ff762b6
...
...
@@ -13,7 +13,12 @@ from capa.tests.helpers import new_loncapa_problem
class
CAPAProblemTest
(
unittest
.
TestCase
):
""" CAPA problem related tests"""
def
test_label_and_description_inside_responsetype
(
self
):
@ddt.unpack
@ddt.data
(
{
'question'
:
'Select the correct synonym of paranoid?'
},
{
'question'
:
'Select the correct <em>synonym</em> of <strong>paranoid</strong>?'
},
)
def
test_label_and_description_inside_responsetype
(
self
,
question
):
"""
Verify that
* label is extracted
...
...
@@ -25,7 +30,7 @@ class CAPAProblemTest(unittest.TestCase):
xml
=
"""
<problem>
<choiceresponse>
<label>
Select the correct synonym of paranoid?
</label>
<label>
{question}
</label>
<description>Only the paranoid survive.</description>
<checkboxgroup>
<choice correct="true">over-suspicious</choice>
...
...
@@ -33,25 +38,35 @@ class CAPAProblemTest(unittest.TestCase):
</checkboxgroup>
</choiceresponse>
</problem>
"""
"""
.
format
(
question
=
question
)
problem
=
new_loncapa_problem
(
xml
)
self
.
assertEqual
(
problem
.
problem_data
,
{
'1_2_1'
:
{
'label'
:
'Select the correct synonym of paranoid?'
,
'label'
:
question
,
'descriptions'
:
{
'description_1_1_1'
:
'Only the paranoid survive.'
}
}
}
)
self
.
assertEqual
(
len
(
problem
.
tree
.
xpath
(
'//label'
)),
0
)
def
test_legacy_problem
(
self
):
@ddt.unpack
@ddt.data
(
{
'question'
:
'Once we become predictable, we become ______?'
,
'label_attr'
:
'Once we become predictable, we become ______?'
},
{
'question'
:
'Once we become predictable, we become ______?<img src="img/src"/>'
,
'label_attr'
:
'Once we become predictable, we become ______?'
},
)
def
test_legacy_problem
(
self
,
question
,
label_attr
):
"""
Verify that legacy problem is handled correctly.
"""
question
=
"Once we become predictable, we become ______?"
xml
=
"""
<problem>
<p>Be sure to check your spelling.</p>
...
...
@@ -60,7 +75,7 @@ class CAPAProblemTest(unittest.TestCase):
<textline label="{}" size="40"/>
</stringresponse>
</problem>
"""
.
format
(
question
,
question
)
"""
.
format
(
question
,
label_attr
)
problem
=
new_loncapa_problem
(
xml
)
self
.
assertEqual
(
problem
.
problem_data
,
...
...
@@ -77,7 +92,18 @@ class CAPAProblemTest(unittest.TestCase):
0
)
def
test_neither_label_tag_nor_attribute
(
self
):
@ddt.unpack
@ddt.data
(
{
'question1'
:
'People who say they have nothing to ____ almost always do?'
,
'question2'
:
'Select the correct synonym of paranoid?'
},
{
'question1'
:
'<b>People</b> who say they have <mark>nothing</mark> to ____ almost always do?'
,
'question2'
:
'Select the <sup>correct</sup> synonym of <mark>paranoid</mark>?'
},
)
def
test_neither_label_tag_nor_attribute
(
self
,
question1
,
question2
):
"""
Verify that label is extracted correctly.
...
...
@@ -86,8 +112,6 @@ class CAPAProblemTest(unittest.TestCase):
tag and label attribute inside responsetype. But we have a label tag
before the responsetype.
"""
question1
=
'People who say they have nothing to ____ almost always do?'
question2
=
'Select the correct synonym of paranoid?'
xml
=
"""
<problem>
<p>Be sure to check your spelling.</p>
...
...
@@ -131,17 +155,19 @@ class CAPAProblemTest(unittest.TestCase):
"""
Verify that multiple descriptions are handled correctly.
"""
desc1
=
"The problem with trying to be the <em>bad guy</em>, there's always someone <strong>worse</strong>."
desc2
=
"Anyone who looks the world as if it was a game of chess deserves to lose."
xml
=
"""
<problem>
<p>Be sure to check your spelling.</p>
<stringresponse answer="War" type="ci">
<label>___ requires sacrifices.</label>
<description>
The problem with trying to be the bad guy, there's always someone worse.
</description>
<description>
Anyone who looks the world as if it was a game of chess deserves to lose.
</description>
<description>
{}
</description>
<description>
{}
</description>
<textline size="40"/>
</stringresponse>
</problem>
"""
"""
.
format
(
desc1
,
desc2
)
problem
=
new_loncapa_problem
(
xml
)
self
.
assertEqual
(
problem
.
problem_data
,
...
...
@@ -150,8 +176,8 @@ class CAPAProblemTest(unittest.TestCase):
{
'label'
:
'___ requires sacrifices.'
,
'descriptions'
:
{
'description_1_1_1'
:
"The problem with trying to be the bad guy, there's always someone worse."
,
'description_1_1_2'
:
"Anyone who looks the world as if it was a game of chess deserves to lose."
'description_1_1_1'
:
desc1
,
'description_1_1_2'
:
desc2
}
}
}
...
...
@@ -298,11 +324,15 @@ class CAPAProblemTest(unittest.TestCase):
1
)
def
test_multiple_inputtypes
(
self
):
@ddt.unpack
@ddt.data
(
{
'group_label'
:
'Choose the correct color'
},
{
'group_label'
:
'Choose the <b>correct</b> <mark>color</mark>'
},
)
def
test_multiple_inputtypes
(
self
,
group_label
):
"""
Verify that group label and labels for individual inputtypes are extracted correctly.
"""
group_label
=
'Choose the correct color'
input1_label
=
'What color is the sky?'
input2_label
=
'What color are pine needles?'
xml
=
"""
...
...
@@ -424,39 +454,6 @@ class CAPAProblemTest(unittest.TestCase):
self
.
assert_question_tag
(
question1
,
question2
,
tag
=
'label'
,
label_attr
=
False
)
self
.
assert_question_tag
(
question1
,
question2
,
tag
=
'p'
,
label_attr
=
True
)
def
test_question_tag_child_left
(
self
):
"""
If the "old" question tag has children, don't delete the children when
transforming to the new label tag.
"""
xml
=
"""
<problem>
<p>Question<img src='img/src'/></p>
<choiceresponse>
<checkboxgroup label="Question">
<choice correct="true">choice1</choice>
<choice correct="false">choice2</choice>
</checkboxgroup>
</choiceresponse>
</problem>
"""
problem
=
new_loncapa_problem
(
xml
)
self
.
assertEqual
(
problem
.
problem_data
,
{
'1_2_1'
:
{
'label'
:
"Question"
,
'descriptions'
:
{}
}
}
)
# img tag is still present within the paragraph, but p text has been deleted
self
.
assertEqual
(
len
(
problem
.
tree
.
xpath
(
'//p'
)),
1
)
self
.
assertEqual
(
problem
.
tree
.
xpath
(
'//p'
)[
0
]
.
text
,
''
)
self
.
assertEqual
(
len
(
problem
.
tree
.
xpath
(
'//p/img'
)),
1
)
@ddt.ddt
class
CAPAMultiInputProblemTest
(
unittest
.
TestCase
):
...
...
common/lib/capa/capa/tests/test_html_render.py
View file @
6ff762b6
...
...
@@ -186,7 +186,7 @@ class CapaHtmlRenderTest(unittest.TestCase):
'trailing_text'
:
''
,
'size'
:
None
,
'response_data'
:
{
'label'
:
''
,
'descriptions'
:
{}},
'describedby'
:
''
'describedby
_html
'
:
''
}
expected_solution_context
=
{
'id'
:
'1_solution_1'
}
...
...
common/lib/capa/capa/tests/test_input_templates.py
View file @
6ff762b6
This diff is collapsed.
Click to expand it.
common/lib/capa/capa/tests/test_inputtypes.py
View file @
6ff762b6
...
...
@@ -78,7 +78,7 @@ class OptionInputTest(unittest.TestCase):
'id'
:
'sky_input'
,
'default_option_text'
:
'Select an option'
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -147,7 +147,7 @@ class ChoiceGroupTest(unittest.TestCase):
'submitted_message'
:
'Answer received.'
,
'name_array_suffix'
:
expected_suffix
,
# what is this for??
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -201,7 +201,7 @@ class JavascriptInputTest(unittest.TestCase):
'display_class'
:
display_class
,
'problem_state'
:
problem_state
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -239,7 +239,7 @@ class TextLineTest(unittest.TestCase):
'trailing_text'
:
''
,
'preprocessor'
:
None
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -278,7 +278,7 @@ class TextLineTest(unittest.TestCase):
'script_src'
:
script
,
},
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -323,7 +323,7 @@ class TextLineTest(unittest.TestCase):
'trailing_text'
:
expected_text
,
'preprocessor'
:
None
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -366,7 +366,7 @@ class FileSubmissionTest(unittest.TestCase):
'allowed_files'
:
'["runme.py", "nooooo.rb", "ohai.java"]'
,
'required_files'
:
'["cookies.py"]'
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -422,7 +422,7 @@ class CodeInputTest(unittest.TestCase):
'tabsize'
:
int
(
tabsize
),
'queue_len'
:
'3'
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -484,7 +484,7 @@ class MatlabTest(unittest.TestCase):
'queue_len'
:
'3'
,
'matlab_editor_js'
:
'/dummy-static/js/vendor/CodeMirror/octave.js'
,
'response_data'
:
{},
'describedby'
:
''
'describedby
_html
'
:
''
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -519,7 +519,7 @@ class MatlabTest(unittest.TestCase):
'queue_len'
:
'3'
,
'matlab_editor_js'
:
'/dummy-static/js/vendor/CodeMirror/octave.js'
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -553,7 +553,7 @@ class MatlabTest(unittest.TestCase):
'queue_len'
:
'0'
,
'matlab_editor_js'
:
'/dummy-static/js/vendor/CodeMirror/octave.js'
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -587,7 +587,7 @@ class MatlabTest(unittest.TestCase):
'queue_len'
:
'1'
,
'matlab_editor_js'
:
'/dummy-static/js/vendor/CodeMirror/octave.js'
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -705,13 +705,14 @@ class MatlabTest(unittest.TestCase):
textwrap
.
dedent
(
"""
<div>{
\'
status
\'
: Status(
\'
queued
\'
),
\'
button_enabled
\'
: True,
\'
rows
\'
:
\'
10
\'
,
\'
queue_len
\'
:
\'
3
\'
,
\'
mode
\'
:
\'\'
,
\'
tabsize
\'
: 4,
\'
cols
\'
:
\'
80
\'
,
\'
STATIC_URL
\'
:
\'
/dummy-static/
\'
,
\'
describedby
\'
:
\'
\'
,
\'
queue_msg
\'
:
\'\'
,
\'
tabsize
\'
: 4,
\'
cols
\'
:
\'
80
\'
,
\'
STATIC_URL
\'
:
\'
/dummy-static/
\'
,
\'
linenumbers
\'
:
\'
true
\'
,
\'
queue_msg
\'
:
\'\'
,
\'
value
\'
:
\'
print "good evening"
\'
,
\'
msg
\'
: u
\'
Submitted. As soon as a response is returned,
this message will be replaced by that feedback.
\'
,
\'
matlab_editor_js
\'
:
\'
/dummy-static/js/vendor/CodeMirror/octave.js
\'
,
\'
hidden
\'
:
\'\'
,
\'
linenumbers
\'
:
\'
true
\'
,
\'
id
\'
:
\'
prob_1_2
\'
,
\'
response_data
\'
: {}}</div>
\'
hidden
\'
:
\'\'
,
\'
id
\'
:
\'
prob_1_2
\'
,
\'
describedby_html
\'
:
\'\'
,
\'
response_data
\'
: {}}</div>
"""
)
.
replace
(
'
\n
'
,
' '
)
.
strip
()
)
...
...
@@ -818,7 +819,7 @@ class MatlabTest(unittest.TestCase):
'queue_len'
:
'3'
,
'matlab_editor_js'
:
'/dummy-static/js/vendor/CodeMirror/octave.js'
,
'response_data'
:
{},
'describedby'
:
''
'describedby
_html
'
:
''
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -929,7 +930,7 @@ class SchematicTest(unittest.TestCase):
'analyses'
:
analyses
,
'submit_analyses'
:
submit_analyses
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -975,7 +976,7 @@ class ImageInputTest(unittest.TestCase):
'gy'
:
egy
,
'msg'
:
''
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -1031,7 +1032,7 @@ class CrystallographyTest(unittest.TestCase):
'width'
:
width
,
'height'
:
height
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -1079,7 +1080,7 @@ class VseprTest(unittest.TestCase):
'molecules'
:
molecules
,
'geometries'
:
geometries
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -1115,7 +1116,7 @@ class ChemicalEquationTest(unittest.TestCase):
'size'
:
self
.
size
,
'previewer'
:
'/dummy-static/js/capa/chemical_equation_preview.js'
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -1210,7 +1211,7 @@ class FormulaEquationTest(unittest.TestCase):
'inline'
:
False
,
'trailing_text'
:
''
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -1256,7 +1257,7 @@ class FormulaEquationTest(unittest.TestCase):
'inline'
:
False
,
'trailing_text'
:
expected_text
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
assertEqual
(
context
,
expected
)
...
...
@@ -1388,7 +1389,7 @@ class DragAndDropTest(unittest.TestCase):
'msg'
:
''
,
'drag_and_drop_json'
:
json
.
dumps
(
user_input
),
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
# as we are dumping 'draggables' dicts while dumping user_input, string
...
...
@@ -1457,7 +1458,7 @@ class AnnotationInputTest(unittest.TestCase):
'debug'
:
False
,
'return_to_annotation'
:
True
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
self
.
maxDiff
=
None
...
...
@@ -1522,7 +1523,7 @@ class TestChoiceText(unittest.TestCase):
'show_correctness'
:
'always'
,
'submitted_message'
:
'Answer received.'
,
'response_data'
:
RESPONSE_DATA
,
'describedby'
:
DESCRIBEDBY
'describedby
_html
'
:
DESCRIBEDBY
}
expected
.
update
(
state
)
the_input
=
lookup_tag
(
tag
)(
test_capa_system
(),
element
,
state
)
...
...
common/lib/capa/capa/tests/test_util.py
View file @
6ff762b6
...
...
@@ -5,7 +5,7 @@ import unittest
from
lxml
import
etree
from
capa.tests.helpers
import
test_capa_system
from
capa.util
import
compare_with_tolerance
,
sanitize_html
,
get_inner_html_from_xpath
from
capa.util
import
compare_with_tolerance
,
sanitize_html
,
get_inner_html_from_xpath
,
remove_markup
class
UtilTest
(
unittest
.
TestCase
):
...
...
@@ -126,3 +126,12 @@ class UtilTest(unittest.TestCase):
"""
xpath_node
=
etree
.
XML
(
'<hint style="smtng">aa<a href="#">bb</a>cc</hint>'
)
self
.
assertEqual
(
get_inner_html_from_xpath
(
xpath_node
),
'aa<a href="#">bb</a>cc'
)
def
test_remove_markup
(
self
):
"""
Test for markup removal with bleach.
"""
self
.
assertEqual
(
remove_markup
(
"The <mark>Truth</mark> is <em>Out There</em> & you need to <strong>find</strong> it"
),
"The Truth is Out There & you need to find it"
)
common/lib/capa/capa/util.py
View file @
6ff762b6
...
...
@@ -8,6 +8,7 @@ from calc import evaluator
from
cmath
import
isinf
,
isnan
import
re
from
lxml
import
etree
from
openedx.core.djangolib.markup
import
HTML
#-----------------------------------------------------------------------------
#
# Utility functions used in CAPA responsetypes
...
...
@@ -195,3 +196,15 @@ def get_inner_html_from_xpath(xpath_node):
# strips outer tag from html string
inner_html
=
re
.
sub
(
'(?ms)<
%
s[^>]*>(.*)</
%
s>'
%
(
xpath_node
.
tag
,
xpath_node
.
tag
),
'
\\
1'
,
html
)
return
inner_html
.
strip
()
def
remove_markup
(
html
):
"""
Return html with markup stripped and text HTML-escaped.
>>> bleach.clean("<b>Rock & Roll</b>", tags=[], strip=True)
u'Rock & Roll'
>>> bleach.clean("<b>Rock & Roll</b>", tags=[], strip=True)
u'Rock & Roll'
"""
return
HTML
(
bleach
.
clean
(
html
,
tags
=
[],
strip
=
True
))
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