escape single quotes in optioninput (optionresponse) tags
STUD-893
This commit is contained in:
@@ -309,6 +309,9 @@ class OptionInput(InputTypeBase):
|
||||
Given options string, convert it into an ordered list of (option_id, option_description) tuples, where
|
||||
id==description for now. TODO: make it possible to specify different id and descriptions.
|
||||
"""
|
||||
# convert single quotes inside option values to html encoded string
|
||||
options = re.sub(r"([a-zA-Z])('|\\')([a-zA-Z])", r"\1'\3", options)
|
||||
options = re.sub(r"\\'", r"'", options) # replace already escaped single quotes
|
||||
# parse the set of possible options
|
||||
lexer = shlex.shlex(options[1:-1].encode('utf8'))
|
||||
lexer.quotes = "'"
|
||||
@@ -316,7 +319,8 @@ class OptionInput(InputTypeBase):
|
||||
lexer.whitespace = ", "
|
||||
|
||||
# remove quotes
|
||||
tokens = [x[1:-1].decode('utf8') for x in lexer]
|
||||
# convert escaped single quotes (html encoded string) back to single quotes
|
||||
tokens = [x[1:-1].decode('utf8').replace("'", "'") for x in lexer]
|
||||
|
||||
# make list of (option_id, option_description), with description=id
|
||||
return [(t, t) for t in tokens]
|
||||
|
||||
@@ -41,7 +41,7 @@ class OptionInputTest(unittest.TestCase):
|
||||
'''
|
||||
|
||||
def test_rendering(self):
|
||||
xml_str = """<optioninput options="('Up','Down')" id="sky_input" correct="Up"/>"""
|
||||
xml_str = """<optioninput options="('Up','Down','Don't know')" id="sky_input" correct="Up"/>"""
|
||||
element = etree.fromstring(xml_str)
|
||||
|
||||
state = {'value': 'Down',
|
||||
@@ -54,7 +54,7 @@ class OptionInputTest(unittest.TestCase):
|
||||
expected = {
|
||||
'STATIC_URL': '/dummy-static/',
|
||||
'value': 'Down',
|
||||
'options': [('Up', 'Up'), ('Down', 'Down')],
|
||||
'options': [('Up', 'Up'), ('Down', 'Down'), ('Don\'t know', 'Don\'t know')],
|
||||
'status': 'answered',
|
||||
'msg': '',
|
||||
'inline': False,
|
||||
@@ -80,6 +80,10 @@ class OptionInputTest(unittest.TestCase):
|
||||
check(u"('б в','в')", [u'б в', u'в'])
|
||||
check(u"('Мой \"кавыки\"место','в')", [u'Мой \"кавыки\"место', u'в'])
|
||||
|
||||
# check that escaping single quotes with leading backslash (\') properly works
|
||||
# note: actual input by user will be hasn\'t but json parses it as hasn\\'t
|
||||
check(u"('hasnt','hasn't')", [u'hasnt', u'hasn\'t'])
|
||||
|
||||
|
||||
class ChoiceGroupTest(unittest.TestCase):
|
||||
'''
|
||||
|
||||
@@ -345,6 +345,17 @@ class OptionResponseTest(ResponseTest):
|
||||
# Options not in the list should be marked incorrect
|
||||
self.assert_grade(problem, "invalid_option", "incorrect")
|
||||
|
||||
def test_quote_option(self):
|
||||
# Test that option response properly escapes quotes inside options strings
|
||||
problem = self.build_problem(options=["hasnot", "hasn't", "has'nt"],
|
||||
correct_option="hasn't")
|
||||
|
||||
# Assert that correct option with a quote inside is marked correctly
|
||||
self.assert_grade(problem, "hasnot", "incorrect")
|
||||
self.assert_grade(problem, "hasn't", "correct")
|
||||
self.assert_grade(problem, "hasn\'t", "correct")
|
||||
self.assert_grade(problem, "has'nt", "incorrect")
|
||||
|
||||
|
||||
class FormulaResponseTest(ResponseTest):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user