Commit 9221450e by Muhammad Ammar Committed by GitHub

Merge pull request #13280 from edx/ammar/make-multi-input-response-accessible

Multiple input types within a response type should be handled correctly.
parents 85e7e70f 1878c7f0
...@@ -765,8 +765,7 @@ class LoncapaProblem(object): ...@@ -765,8 +765,7 @@ class LoncapaProblem(object):
if problemtree.tag in inputtypes.registry.registered_tags(): if problemtree.tag in inputtypes.registry.registered_tags():
# If this is an inputtype subtree, let it render itself. # If this is an inputtype subtree, let it render itself.
response_id = self.problem_id + '_' + problemtree.get('response_id') response_data = self.problem_data[problemid]
response_data = self.problem_data[response_id]
status = 'unsubmitted' status = 'unsubmitted'
msg = '' msg = ''
...@@ -856,16 +855,16 @@ class LoncapaProblem(object): ...@@ -856,16 +855,16 @@ class LoncapaProblem(object):
problem_data = {} problem_data = {}
self.responders = {} self.responders = {}
for response in tree.xpath('//' + "|//".join(responsetypes.registry.registered_tags())): for response in tree.xpath('//' + "|//".join(responsetypes.registry.registered_tags())):
response_id_str = self.problem_id + "_" + str(response_id) responsetype_id = self.problem_id + "_" + str(response_id)
# create and save ID for this response # create and save ID for this response
response.set('id', response_id_str) response.set('id', responsetype_id)
response_id += 1 response_id += 1
answer_id = 1 answer_id = 1
input_tags = inputtypes.registry.registered_tags() input_tags = inputtypes.registry.registered_tags()
inputfields = tree.xpath( inputfields = tree.xpath(
"|".join(['//' + response.tag + '[@id=$id]//' + x for x in input_tags]), "|".join(['//' + response.tag + '[@id=$id]//' + x for x in input_tags]),
id=response_id_str id=responsetype_id
) )
# assign one answer_id for each input type # assign one answer_id for each input type
...@@ -875,10 +874,65 @@ class LoncapaProblem(object): ...@@ -875,10 +874,65 @@ class LoncapaProblem(object):
entry.attrib['id'] = "%s_%i_%i" % (self.problem_id, response_id, answer_id) entry.attrib['id'] = "%s_%i_%i" % (self.problem_id, response_id, answer_id)
answer_id = answer_id + 1 answer_id = answer_id + 1
question_id = u'{}_{}'.format(self.problem_id, response_id) self.response_a11y_data(response, inputfields, responsetype_id, problem_data)
label = ''
element_to_be_deleted = None
# instantiate capa Response
responsetype_cls = responsetypes.registry.get_class_for_tag(response.tag)
responder = responsetype_cls(response, inputfields, self.context, self.capa_system, self.capa_module)
# save in list in self
self.responders[response] = responder
# get responder answers (do this only once, since there may be a performance cost,
# eg with externalresponse)
self.responder_answers = {}
for response in self.responders.keys():
try:
self.responder_answers[response] = self.responders[response].get_answers()
except:
log.debug('responder %s failed to properly return get_answers()',
self.responders[response]) # FIXME
raise
# <solution>...</solution> may not be associated with any specific response; give
# IDs for those separately
# TODO: We should make the namespaces consistent and unique (e.g. %s_problem_%i).
solution_id = 1
for solution in tree.findall('.//solution'):
solution.attrib['id'] = "%s_solution_%i" % (self.problem_id, solution_id)
solution_id += 1
return problem_data
def response_a11y_data(self, response, inputfields, responsetype_id, problem_data):
"""
Construct data to be used for a11y.
Arguments:
response (object): xml response object
inputfields (list): list of inputfields in a responsetype
responsetype_id (str): responsetype id
problem_data (dict): dict to be filled with response data
"""
element_to_be_deleted = None
label = ''
if len(inputfields) > 1:
response.set('multiple_inputtypes', 'true')
group_label_tag = response.find('label')
group_label_tag_text = ''
if group_label_tag is not None:
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
for inputfield in inputfields:
problem_data[inputfield.get('id')] = {
'group_label': group_label_tag_text,
'label': inputfield.attrib.get('label', ''),
'descriptions': {}
}
else:
# Extract label value from <label> tag or label attribute from inside the responsetype # Extract label value from <label> tag or label attribute from inside the responsetype
responsetype_label_tag = response.find('label') responsetype_label_tag = response.find('label')
if responsetype_label_tag is not None: if responsetype_label_tag is not None:
...@@ -930,39 +984,12 @@ class LoncapaProblem(object): ...@@ -930,39 +984,12 @@ class LoncapaProblem(object):
descriptions = OrderedDict() descriptions = OrderedDict()
for description in description_tags: for description in description_tags:
descriptions[ descriptions[
"description_%s_%i_%i" % (self.problem_id, response_id, description_id) "description_%s_%i" % (responsetype_id, description_id)
] = description.text ] = description.text
response.remove(description) response.remove(description)
description_id += 1 description_id += 1
problem_data[question_id] = { problem_data[inputfields[0].get('id')] = {
'label': label, 'label': label,
'descriptions': descriptions 'descriptions': descriptions
} }
# instantiate capa Response
responsetype_cls = responsetypes.registry.get_class_for_tag(response.tag)
responder = responsetype_cls(response, inputfields, self.context, self.capa_system, self.capa_module)
# save in list in self
self.responders[response] = responder
# get responder answers (do this only once, since there may be a performance cost,
# eg with externalresponse)
self.responder_answers = {}
for response in self.responders.keys():
try:
self.responder_answers[response] = self.responders[response].get_answers()
except:
log.debug('responder %s failed to properly return get_answers()',
self.responders[response]) # FIXME
raise
# <solution>...</solution> may not be associated with any specific response; give
# IDs for those separately
# TODO: We should make the namespaces consistent and unique (e.g. %s_problem_%i).
solution_id = 1
for solution in tree.findall('.//solution'):
solution.attrib['id'] = "%s_solution_%i" % (self.problem_id, solution_id)
solution_id += 1
return problem_data
...@@ -263,6 +263,15 @@ class LoncapaResponse(object): ...@@ -263,6 +263,15 @@ class LoncapaResponse(object):
tree.set('tabindex', '-1') tree.set('tabindex', '-1')
tree.set('aria-label', response_label) tree.set('aria-label', response_label)
if self.xml.get('multiple_inputtypes'):
# add <div> to wrap all inputtypes
content = etree.SubElement(tree, 'div')
content.set('class', 'multi-inputs-group')
content.set('role', 'group')
content.set('aria-labelledby', self.xml.get('id'))
else:
content = tree
# problem author can make this span display:inline # problem author can make this span display:inline
if self.xml.get('inline', ''): if self.xml.get('inline', ''):
tree.set('class', 'inline') tree.set('class', 'inline')
...@@ -271,12 +280,12 @@ class LoncapaResponse(object): ...@@ -271,12 +280,12 @@ class LoncapaResponse(object):
# call provided procedure to do the rendering # call provided procedure to do the rendering
item_xhtml = renderer(item) item_xhtml = renderer(item)
if item_xhtml is not None: if item_xhtml is not None:
tree.append(item_xhtml) content.append(item_xhtml)
tree.tail = self.xml.tail tree.tail = self.xml.tail
# Add a <div> for the message at the end of the response # Add a <div> for the message at the end of the response
if response_msg: if response_msg:
tree.append(self._render_response_msg_html(response_msg)) content.append(self._render_response_msg_html(response_msg))
return tree return tree
......
"""Tools for helping with testing capa.""" """Tools for helping with testing capa."""
import gettext import gettext
from path import path # pylint: disable=no-name-in-module
import os import os
import os.path import os.path
...@@ -9,12 +10,29 @@ import fs.osfs ...@@ -9,12 +10,29 @@ import fs.osfs
from capa.capa_problem import LoncapaProblem, LoncapaSystem from capa.capa_problem import LoncapaProblem, LoncapaSystem
from capa.inputtypes import Status from capa.inputtypes import Status
from mock import Mock, MagicMock from mock import Mock, MagicMock
from mako.lookup import TemplateLookup
import xml.sax.saxutils as saxutils import xml.sax.saxutils as saxutils
TEST_DIR = os.path.dirname(os.path.realpath(__file__)) TEST_DIR = os.path.dirname(os.path.realpath(__file__))
def get_template(template_name):
"""
Return template for a capa inputtype.
"""
return TemplateLookup(
directories=[path(__file__).dirname().dirname() / 'templates']
).get_template(template_name)
def capa_render_template(template, context):
"""
Render template for a capa inputtype.
"""
return get_template(template).render_unicode(**context)
def tst_render_template(template, context): def tst_render_template(template, context):
""" """
A test version of render to template. Renders to the repr of the context, completely ignoring A test version of render to template. Renders to the repr of the context, completely ignoring
...@@ -30,7 +48,7 @@ xqueue_interface = MagicMock() ...@@ -30,7 +48,7 @@ xqueue_interface = MagicMock()
xqueue_interface.send_to_queue.return_value = (0, 'Success!') xqueue_interface.send_to_queue.return_value = (0, 'Success!')
def test_capa_system(): def test_capa_system(render_template=None):
""" """
Construct a mock LoncapaSystem instance. Construct a mock LoncapaSystem instance.
...@@ -46,7 +64,7 @@ def test_capa_system(): ...@@ -46,7 +64,7 @@ def test_capa_system():
filestore=fs.osfs.OSFS(os.path.join(TEST_DIR, "test_files")), filestore=fs.osfs.OSFS(os.path.join(TEST_DIR, "test_files")),
i18n=gettext.NullTranslations(), i18n=gettext.NullTranslations(),
node_path=os.environ.get("NODE_PATH", "/usr/local/lib/node_modules"), node_path=os.environ.get("NODE_PATH", "/usr/local/lib/node_modules"),
render_template=tst_render_template, render_template=render_template or tst_render_template,
seed=0, seed=0,
STATIC_URL='/dummy-static/', STATIC_URL='/dummy-static/',
STATUS_CLASS=Status, STATUS_CLASS=Status,
...@@ -66,9 +84,10 @@ def mock_capa_module(): ...@@ -66,9 +84,10 @@ def mock_capa_module():
return capa_module return capa_module
def new_loncapa_problem(xml, capa_system=None, seed=723): def new_loncapa_problem(xml, capa_system=None, seed=723, use_capa_render_template=False):
"""Construct a `LoncapaProblem` suitable for unit tests.""" """Construct a `LoncapaProblem` suitable for unit tests."""
return LoncapaProblem(xml, id='1', seed=seed, capa_system=capa_system or test_capa_system(), render_template = capa_render_template if use_capa_render_template else None
return LoncapaProblem(xml, id='1', seed=seed, capa_system=capa_system or test_capa_system(render_template),
capa_module=mock_capa_module()) capa_module=mock_capa_module())
......
...@@ -267,6 +267,9 @@ class CustomResponseXMLFactory(ResponseXMLFactory): ...@@ -267,6 +267,9 @@ class CustomResponseXMLFactory(ResponseXMLFactory):
*answer_attr*: The "answer" attribute on the tag itself (treated as an *answer_attr*: The "answer" attribute on the tag itself (treated as an
alias to "expect", though "expect" takes priority if both are given) alias to "expect", though "expect" takes priority if both are given)
*group_label*: Text to represent group of inputs when there are
multiple inputs.
""" """
# Retrieve **kwargs # Retrieve **kwargs
...@@ -276,6 +279,7 @@ class CustomResponseXMLFactory(ResponseXMLFactory): ...@@ -276,6 +279,7 @@ class CustomResponseXMLFactory(ResponseXMLFactory):
answer = kwargs.get('answer', None) answer = kwargs.get('answer', None)
options = kwargs.get('options', None) options = kwargs.get('options', None)
cfn_extra_args = kwargs.get('cfn_extra_args', None) cfn_extra_args = kwargs.get('cfn_extra_args', None)
group_label = kwargs.get('group_label', None)
# Create the response element # Create the response element
response_element = etree.Element("customresponse") response_element = etree.Element("customresponse")
...@@ -293,6 +297,10 @@ class CustomResponseXMLFactory(ResponseXMLFactory): ...@@ -293,6 +297,10 @@ class CustomResponseXMLFactory(ResponseXMLFactory):
answer_element = etree.SubElement(response_element, "answer") answer_element = etree.SubElement(response_element, "answer")
answer_element.text = str(answer) answer_element.text = str(answer)
if group_label:
group_label_element = etree.SubElement(response_element, "label")
group_label_element.text = group_label
if options: if options:
response_element.set('options', str(options)) response_element.set('options', str(options))
......
""" """
Test capa problem. Test capa problem.
""" """
import ddt
import textwrap
from lxml import etree
import unittest import unittest
from . import new_loncapa_problem from . import new_loncapa_problem
...@@ -35,10 +38,10 @@ class CAPAProblemTest(unittest.TestCase): ...@@ -35,10 +38,10 @@ class CAPAProblemTest(unittest.TestCase):
self.assertEqual( self.assertEqual(
problem.problem_data, problem.problem_data,
{ {
'1_2': '1_2_1':
{ {
'label': 'Select the correct synonym of paranoid?', 'label': 'Select the correct synonym of paranoid?',
'descriptions': {'description_1_2_1': 'Only the paranoid survive.'} 'descriptions': {'description_1_1_1': 'Only the paranoid survive.'}
} }
} }
) )
...@@ -62,7 +65,13 @@ class CAPAProblemTest(unittest.TestCase): ...@@ -62,7 +65,13 @@ class CAPAProblemTest(unittest.TestCase):
problem = new_loncapa_problem(xml) problem = new_loncapa_problem(xml)
self.assertEqual( self.assertEqual(
problem.problem_data, problem.problem_data,
{'1_2': {'label': question, 'descriptions': {}}} {
'1_2_1':
{
'label': question,
'descriptions': {}
}
}
) )
self.assertEqual( self.assertEqual(
...@@ -101,12 +110,12 @@ class CAPAProblemTest(unittest.TestCase): ...@@ -101,12 +110,12 @@ class CAPAProblemTest(unittest.TestCase):
self.assertEqual( self.assertEqual(
problem.problem_data, problem.problem_data,
{ {
'1_2': '1_2_1':
{ {
'label': question1, 'label': question1,
'descriptions': {} 'descriptions': {}
}, },
'1_3': '1_3_1':
{ {
'label': question2, 'label': question2,
'descriptions': {} 'descriptions': {}
...@@ -139,12 +148,12 @@ class CAPAProblemTest(unittest.TestCase): ...@@ -139,12 +148,12 @@ class CAPAProblemTest(unittest.TestCase):
self.assertEqual( self.assertEqual(
problem.problem_data, problem.problem_data,
{ {
'1_2': '1_2_1':
{ {
'label': '___ requires sacrifices.', 'label': '___ requires sacrifices.',
'descriptions': { 'descriptions': {
'description_1_2_1': "The problem with trying to be the bad guy, there's always someone worse.", 'description_1_1_1': "The problem with trying to be the bad guy, there's always someone worse.",
'description_1_2_2': "Anyone who looks the world as if it was a game of chess deserves to lose." 'description_1_1_2': "Anyone who looks the world as if it was a game of chess deserves to lose."
} }
} }
} }
...@@ -167,11 +176,11 @@ class CAPAProblemTest(unittest.TestCase): ...@@ -167,11 +176,11 @@ class CAPAProblemTest(unittest.TestCase):
self.assertEqual( self.assertEqual(
problem.problem_data, problem.problem_data,
{ {
'1_2': '1_2_1':
{ {
'label': DEFAULT_QUESTION_TEXT, 'label': DEFAULT_QUESTION_TEXT,
'descriptions': { 'descriptions': {
'description_1_2_1': "Everybody needs somebody to talk to." 'description_1_1_1': "Everybody needs somebody to talk to."
} }
} }
} }
...@@ -195,7 +204,7 @@ class CAPAProblemTest(unittest.TestCase): ...@@ -195,7 +204,7 @@ class CAPAProblemTest(unittest.TestCase):
self.assertEqual( self.assertEqual(
problem.problem_data, problem.problem_data,
{ {
'1_2': '1_2_1':
{ {
'label': 'Click the country which is home to the Pyramids.', 'label': 'Click the country which is home to the Pyramids.',
'descriptions': {} 'descriptions': {}
...@@ -224,7 +233,7 @@ class CAPAProblemTest(unittest.TestCase): ...@@ -224,7 +233,7 @@ class CAPAProblemTest(unittest.TestCase):
self.assertEqual( self.assertEqual(
problem.problem_data, problem.problem_data,
{ {
'1_2': '1_2_1':
{ {
'label': '', 'label': '',
'descriptions': {} 'descriptions': {}
...@@ -266,15 +275,15 @@ class CAPAProblemTest(unittest.TestCase): ...@@ -266,15 +275,15 @@ class CAPAProblemTest(unittest.TestCase):
self.assertEqual( self.assertEqual(
problem.problem_data, problem.problem_data,
{ {
'1_2': '1_2_1':
{ {
'label': 'Select the correct synonym of paranoid?', 'label': 'Select the correct synonym of paranoid?',
'descriptions': {'description_1_2_1': 'Only the paranoid survive.'} 'descriptions': {'description_1_1_1': 'Only the paranoid survive.'}
}, },
'1_3': '1_3_1':
{ {
'label': 'What Apple device competed with the portable CD player?', 'label': 'What Apple device competed with the portable CD player?',
'descriptions': {'description_1_3_1': 'Device looks like an egg plant.'} 'descriptions': {'description_1_2_1': 'Device looks like an egg plant.'}
} }
} }
) )
...@@ -306,7 +315,7 @@ class CAPAProblemTest(unittest.TestCase): ...@@ -306,7 +315,7 @@ class CAPAProblemTest(unittest.TestCase):
self.assertEqual( self.assertEqual(
problem.problem_data, problem.problem_data,
{ {
'1_2': '1_2_1':
{ {
'label': question, 'label': question,
'descriptions': {} 'descriptions': {}
...@@ -317,3 +326,146 @@ class CAPAProblemTest(unittest.TestCase): ...@@ -317,3 +326,146 @@ class CAPAProblemTest(unittest.TestCase):
len(problem.tree.xpath('//p[text()="{}"]'.format(question))), len(problem.tree.xpath('//p[text()="{}"]'.format(question))),
0 0
) )
def test_multiple_inputtypes(self):
"""
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 = """
<problem>
<optionresponse>
<label>{}</label>
<optioninput options="('yellow','blue','green')" correct="blue" label="{}"/>
<optioninput options="('yellow','blue','green')" correct="green" label="{}"/>
</optionresponse>
</problem>
""".format(group_label, input1_label, input2_label)
problem = new_loncapa_problem(xml)
self.assertEqual(
problem.problem_data,
{
'1_2_1':
{
'group_label': group_label,
'label': input1_label,
'descriptions': {}
},
'1_2_2':
{
'group_label': group_label,
'label': input2_label,
'descriptions': {}
}
}
)
def test_single_inputtypes(self):
"""
Verify that HTML is correctly rendered when there is single inputtype.
"""
xml = """
<problem>
<choiceresponse>
<label>Select the correct synonym of paranoid?</label>
<description>Only the paranoid survive.</description>
<checkboxgroup>
<choice correct="true">over-suspicious</choice>
<choice correct="false">funny</choice>
</checkboxgroup>
</choiceresponse>
</problem>
"""
problem = new_loncapa_problem(xml, use_capa_render_template=True)
problem_html = etree.XML(problem.get_html())
# verify that only no multi input group div is present
multi_inputs_group = problem_html.xpath('//div[@class="multi-inputs-group"]')
self.assertEqual(len(multi_inputs_group), 0)
@ddt.ddt
class CAPAMultiInputProblemTest(unittest.TestCase):
""" TestCase for CAPA problems with multiple inputtypes """
def capa_problem(self, xml):
"""
Create capa problem.
"""
return new_loncapa_problem(xml, use_capa_render_template=True)
def assert_problem_html(self, problme_html, group_label, *input_labels):
"""
Verify that correct html is rendered for multiple inputtypes.
"""
html = etree.XML(problme_html)
# verify that only one multi input group div is present at correct path
multi_inputs_group = html.xpath(
'//section[@class="wrapper-problem-response"]/div[@class="multi-inputs-group"]'
)
self.assertEqual(len(multi_inputs_group), 1)
# verify that multi input group label <p> tag exists and its
# id matches with correct multi input group aria-labelledby
multi_inputs_group_label_id = multi_inputs_group[0].attrib.get('aria-labelledby')
multi_inputs_group_label = html.xpath('//p[@id="{}"]'.format(multi_inputs_group_label_id))
self.assertEqual(len(multi_inputs_group_label), 1)
self.assertEqual(multi_inputs_group_label[0].text, group_label)
# verify that label for each input comes only once
for input_label in input_labels:
# normalize-space is used to remove whitespace around the text
input_label_element = multi_inputs_group[0].xpath('//*[normalize-space(text())="{}"]'.format(input_label))
self.assertEqual(len(input_label_element), 1)
def test_optionresponse(self):
"""
Verify that optionresponse problem with multiple inputtypes is rendered correctly.
"""
group_label = 'Choose the correct color'
input1_label = 'What color is the sky?'
input2_label = 'What color are pine needles?'
xml = """
<problem>
<optionresponse>
<label>{}</label>
<optioninput options="('yellow','blue','green')" correct="blue" label="{}"/>
<optioninput options="('yellow','blue','green')" correct="green" label="{}"/>
</optionresponse>
</problem>
""".format(group_label, input1_label, input2_label)
problem = self.capa_problem(xml)
self.assert_problem_html(problem.get_html(), group_label, input1_label, input2_label)
@ddt.unpack
@ddt.data(
{'inputtype': 'textline'},
{'inputtype': 'formulaequationinput'}
)
def test_customresponse(self, inputtype):
"""
Verify that customresponse problem with multiple textline
and formulaequationinput inputtypes is rendered correctly.
"""
group_label = 'Enter two integers that sum to 10.'
input1_label = 'Integer 1'
input2_label = 'Integer 2'
xml = textwrap.dedent("""
<problem>
<customresponse cfn="test_add_to_ten">
<script type="loncapa/python">
def test_add_to_ten(expect, ans):
return test_add(10, ans)
</script>
<label>{}</label>
<{inputtype} size="40" correct_answer="3" label="{}" /><br/>
<{inputtype} size="40" correct_answer="7" label="{}" />
</customresponse>
</problem>
""".format(group_label, input1_label, input2_label, inputtype=inputtype))
problem = self.capa_problem(xml)
self.assert_problem_html(problem.get_html(), group_label, input1_label, input2_label)
...@@ -1296,6 +1296,9 @@ class CapaMixin(CapaFields): ...@@ -1296,6 +1296,9 @@ class CapaMixin(CapaFields):
'correct': is_correct, 'correct': is_correct,
'variant': variant, 'variant': variant,
} }
# Add group_label in event data only if the responsetype contains multiple inputtypes
if answer_input.response_data.get('group_label'):
input_metadata[input_id]['group_label'] = answer_input.response_data.get('group_label')
return input_metadata return input_metadata
......
...@@ -2662,19 +2662,19 @@ class TestProblemCheckTracking(unittest.TestCase): ...@@ -2662,19 +2662,19 @@ class TestProblemCheckTracking(unittest.TestCase):
}) })
def test_multiple_inputs(self): def test_multiple_inputs(self):
group_label = 'Choose the correct color'
input1_label = 'What color is the sky?'
input2_label = 'What color are pine needles?'
factory = self.capa_factory_for_problem_xml("""\ factory = self.capa_factory_for_problem_xml("""\
<problem display_name="Multiple Inputs"> <problem display_name="Multiple Inputs">
<p>Choose the correct color</p>
<optionresponse> <optionresponse>
<p>What color is the sky?</p> <label>{}</label>
<optioninput options="('yellow','blue','green')" correct="blue"/> <optioninput options="('yellow','blue','green')" correct="blue" label="{}"/>
<p>What color are pine needles?</p> <optioninput options="('yellow','blue','green')" correct="green" label="{}"/>
<optioninput options="('yellow','blue','green')" correct="green"/>
</optionresponse> </optionresponse>
</problem> </problem>
""") """.format(group_label, input1_label, input2_label))
module = factory.create() module = factory.create()
answer_input_dict = { answer_input_dict = {
factory.input_key(2, 1): 'blue', factory.input_key(2, 1): 'blue',
factory.input_key(2, 2): 'yellow', factory.input_key(2, 2): 'yellow',
...@@ -2683,7 +2683,8 @@ class TestProblemCheckTracking(unittest.TestCase): ...@@ -2683,7 +2683,8 @@ class TestProblemCheckTracking(unittest.TestCase):
event = self.get_event_for_answers(module, answer_input_dict) event = self.get_event_for_answers(module, answer_input_dict)
self.assertEquals(event['submission'], { self.assertEquals(event['submission'], {
factory.answer_key(2, 1): { factory.answer_key(2, 1): {
'question': DEFAULT_QUESTION_TEXT, 'group_label': group_label,
'question': input1_label,
'answer': 'blue', 'answer': 'blue',
'response_type': 'optionresponse', 'response_type': 'optionresponse',
'input_type': 'optioninput', 'input_type': 'optioninput',
...@@ -2691,7 +2692,8 @@ class TestProblemCheckTracking(unittest.TestCase): ...@@ -2691,7 +2692,8 @@ class TestProblemCheckTracking(unittest.TestCase):
'variant': '', 'variant': '',
}, },
factory.answer_key(2, 2): { factory.answer_key(2, 2): {
'question': DEFAULT_QUESTION_TEXT, 'group_label': group_label,
'question': input2_label,
'answer': 'yellow', 'answer': 'yellow',
'response_type': 'optionresponse', 'response_type': 'optionresponse',
'input_type': 'optioninput', 'input_type': 'optioninput',
...@@ -2702,11 +2704,14 @@ class TestProblemCheckTracking(unittest.TestCase): ...@@ -2702,11 +2704,14 @@ class TestProblemCheckTracking(unittest.TestCase):
def test_optioninput_extended_xml(self): def test_optioninput_extended_xml(self):
"""Test the new XML form of writing with <option> tag instead of options= attribute.""" """Test the new XML form of writing with <option> tag instead of options= attribute."""
group_label = 'Are you the Gatekeeper?'
input1_label = 'input 1 label'
input2_label = 'input 2 label'
factory = self.capa_factory_for_problem_xml("""\ factory = self.capa_factory_for_problem_xml("""\
<problem display_name="Woo Hoo"> <problem display_name="Woo Hoo">
<p>Are you the Gatekeeper?</p>
<optionresponse> <optionresponse>
<optioninput> <label>{}</label>
<optioninput label="{}">
<option correct="True" label="Good Job"> <option correct="True" label="Good Job">
apple apple
<optionhint> <optionhint>
...@@ -2721,7 +2726,7 @@ class TestProblemCheckTracking(unittest.TestCase): ...@@ -2721,7 +2726,7 @@ class TestProblemCheckTracking(unittest.TestCase):
</option> </option>
</optioninput> </optioninput>
<optioninput> <optioninput label="{}">
<option correct="True"> <option correct="True">
apple apple
<optionhint> <optionhint>
...@@ -2737,7 +2742,7 @@ class TestProblemCheckTracking(unittest.TestCase): ...@@ -2737,7 +2742,7 @@ class TestProblemCheckTracking(unittest.TestCase):
</optioninput> </optioninput>
</optionresponse> </optionresponse>
</problem> </problem>
""") """.format(group_label, input1_label, input2_label))
module = factory.create() module = factory.create()
answer_input_dict = { answer_input_dict = {
...@@ -2748,7 +2753,8 @@ class TestProblemCheckTracking(unittest.TestCase): ...@@ -2748,7 +2753,8 @@ class TestProblemCheckTracking(unittest.TestCase):
event = self.get_event_for_answers(module, answer_input_dict) event = self.get_event_for_answers(module, answer_input_dict)
self.assertEquals(event['submission'], { self.assertEquals(event['submission'], {
factory.answer_key(2, 1): { factory.answer_key(2, 1): {
'question': DEFAULT_QUESTION_TEXT, 'group_label': group_label,
'question': input1_label,
'answer': 'apple', 'answer': 'apple',
'response_type': 'optionresponse', 'response_type': 'optionresponse',
'input_type': 'optioninput', 'input_type': 'optioninput',
...@@ -2756,7 +2762,8 @@ class TestProblemCheckTracking(unittest.TestCase): ...@@ -2756,7 +2762,8 @@ class TestProblemCheckTracking(unittest.TestCase):
'variant': '', 'variant': '',
}, },
factory.answer_key(2, 2): { factory.answer_key(2, 2): {
'question': DEFAULT_QUESTION_TEXT, 'group_label': group_label,
'question': input2_label,
'answer': 'cucumber', 'answer': 'cucumber',
'response_type': 'optionresponse', 'response_type': 'optionresponse',
'input_type': 'optioninput', 'input_type': 'optioninput',
......
...@@ -592,10 +592,10 @@ class ScriptProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin): ...@@ -592,10 +592,10 @@ class ScriptProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
factory = CustomResponseXMLFactory() factory = CustomResponseXMLFactory()
factory_kwargs = { factory_kwargs = {
'question_text': 'Enter two integers that sum to 10.',
'cfn': 'test_add_to_ten', 'cfn': 'test_add_to_ten',
'expect': '10', 'expect': '10',
'num_inputs': 2, 'num_inputs': 2,
'group_label': 'Enter two integers that sum to 10.',
'script': textwrap.dedent(""" 'script': textwrap.dedent("""
def test_add_to_ten(expect,ans): def test_add_to_ten(expect,ans):
try: try:
...@@ -618,12 +618,6 @@ class ScriptProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin): ...@@ -618,12 +618,6 @@ class ScriptProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
Additional setup for ScriptProblemTypeTest Additional setup for ScriptProblemTypeTest
""" """
super(ScriptProblemTypeTest, self).setUp(*args, **kwargs) super(ScriptProblemTypeTest, self).setUp(*args, **kwargs)
self.problem_page.a11y_audit.config.set_rules({
'ignore': [
'section', # TODO: AC-491
'label', # TODO: AC-287
]
})
def answer_problem(self, correct): def answer_problem(self, correct):
""" """
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment