diff --git a/common/lib/capa/capa/capa_problem.py b/common/lib/capa/capa/capa_problem.py
index be6c8549ec..c200cf4fd6 100644
--- a/common/lib/capa/capa/capa_problem.py
+++ b/common/lib/capa/capa/capa_problem.py
@@ -46,6 +46,7 @@ ACCESSIBLE_CAPA_INPUT_TYPES = [
'optioninput',
'textline',
'formulaequationinput',
+ 'textbox',
]
# these get captured as student responses
diff --git a/common/lib/capa/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py
index 1365fde94a..25b5fe30b2 100644
--- a/common/lib/capa/capa/inputtypes.py
+++ b/common/lib/capa/capa/inputtypes.py
@@ -818,8 +818,17 @@ class CodeInput(InputTypeBase):
self.setup_code_response_rendering()
def _extra_context(self):
- """Defined queue_len, add it """
- return {'queue_len': self.queue_len, }
+ """
+ Define queue_len, arial_label and code mirror exit message context variables
+ """
+ _ = self.capa_system.i18n.ugettext
+ return {
+ 'queue_len': self.queue_len,
+ 'aria_label': _('{programming_language} editor').format(
+ programming_language=self.loaded_attributes.get('mode')
+ ),
+ 'code_mirror_exit_message': _('Press ESC then TAB or click outside of the code editor to exit')
+ }
#-----------------------------------------------------------------------------
diff --git a/common/lib/capa/capa/responsetypes.py b/common/lib/capa/capa/responsetypes.py
index 7482ca72a2..447a34e7c6 100644
--- a/common/lib/capa/capa/responsetypes.py
+++ b/common/lib/capa/capa/responsetypes.py
@@ -253,23 +253,26 @@ class LoncapaResponse(object):
"""
_ = self.capa_system.i18n.ugettext
- # get responsetype index to make responsetype label
- response_index = self.xml.attrib['id'].split('_')[-1]
+ # response_id = problem_id + response index
+ response_id = self.xml.attrib['id']
+
+ response_index = response_id.split('_')[-1]
# Translators: index here could be 1,2,3 and so on
response_label = _(u'Question {index}').format(index=response_index)
# wrap the content inside a section
- tree = etree.Element('section')
+ tree = etree.Element('div')
tree.set('class', 'wrapper-problem-response')
tree.set('tabindex', '-1')
tree.set('aria-label', response_label)
+ tree.set('role', 'group')
if self.xml.get('multiple_inputtypes'):
# add
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'))
+ content.set('aria-labelledby', response_id)
else:
content = tree
diff --git a/common/lib/capa/capa/templates/codeinput.html b/common/lib/capa/capa/templates/codeinput.html
index f2bffdbf57..57d4d82807 100644
--- a/common/lib/capa/capa/templates/codeinput.html
+++ b/common/lib/capa/capa/templates/codeinput.html
@@ -1,12 +1,16 @@
+<%page expression_filter="h"/>
<%!
from django.utils.translation import ugettext as _
from openedx.core.djangolib.markup import HTML
%>
-
-
+
+ ${code_mirror_exit_message}
+
${HTML(msg)}
-
+
diff --git a/common/lib/capa/capa/tests/helpers.py b/common/lib/capa/capa/tests/helpers.py
index 7ae7a3020d..8947a93552 100644
--- a/common/lib/capa/capa/tests/helpers.py
+++ b/common/lib/capa/capa/tests/helpers.py
@@ -90,10 +90,10 @@ def mock_capa_module():
return capa_module
-def new_loncapa_problem(xml, capa_system=None, seed=723, use_capa_render_template=False):
+def new_loncapa_problem(xml, problem_id='1', capa_system=None, seed=723, use_capa_render_template=False):
"""Construct a `LoncapaProblem` suitable for unit tests."""
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),
+ return LoncapaProblem(xml, id=problem_id, seed=seed, capa_system=capa_system or test_capa_system(render_template),
capa_module=mock_capa_module())
diff --git a/common/lib/capa/capa/tests/test_capa_problem.py b/common/lib/capa/capa/tests/test_capa_problem.py
index 381f0d0722..9f2888180e 100644
--- a/common/lib/capa/capa/tests/test_capa_problem.py
+++ b/common/lib/capa/capa/tests/test_capa_problem.py
@@ -473,7 +473,7 @@ class CAPAMultiInputProblemTest(unittest.TestCase):
# 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"]'
+ '//div[@class="wrapper-problem-response"]/div[@class="multi-inputs-group"]'
)
self.assertEqual(len(multi_inputs_group), 1)
diff --git a/common/lib/capa/capa/tests/test_html_render.py b/common/lib/capa/capa/tests/test_html_render.py
index db1527281b..c2a9491855 100644
--- a/common/lib/capa/capa/tests/test_html_render.py
+++ b/common/lib/capa/capa/tests/test_html_render.py
@@ -1,3 +1,7 @@
+"""
+CAPA HTML rendering tests.
+"""
+import ddt
import unittest
from lxml import etree
import os
@@ -9,7 +13,11 @@ from .response_xml_factory import StringResponseXMLFactory, CustomResponseXMLFac
from capa.tests.helpers import test_capa_system, new_loncapa_problem
+@ddt.ddt
class CapaHtmlRenderTest(unittest.TestCase):
+ """
+ CAPA HTML rendering tests class.
+ """
def setUp(self):
super(CapaHtmlRenderTest, self).setUp()
@@ -142,28 +150,28 @@ class CapaHtmlRenderTest(unittest.TestCase):
# Mock out the template renderer
the_system = test_capa_system()
the_system.render_template = mock.Mock()
- the_system.render_template.return_value = "
Input Template Render
"
+ the_system.render_template.return_value = "
Input Template Render
"
# Create the problem and render the HTML
problem = new_loncapa_problem(xml_str, capa_system=the_system)
rendered_html = etree.XML(problem.get_html())
-
# Expect problem has been turned into a
self.assertEqual(rendered_html.tag, "div")
- # Expect that the response has been turned into a with correct attributes
- response_element = rendered_html.find("section")
- self.assertEqual(response_element.tag, "section")
+ # Expect that the response has been turned into a
with correct attributes
+ response_element = rendered_html.find('div')
+
+ self.assertEqual(response_element.tag, "div")
self.assertEqual(response_element.attrib["aria-label"], "Question 1")
- # Expect that the response
+ # Expect that the response div.wrapper-problem-response
# that contains a
for the textline
- textline_element = response_element.find("div")
+ textline_element = response_element.find('div')
self.assertEqual(textline_element.text, 'Input Template Render')
# Expect a child
for the solution
# with the rendered template
- solution_element = rendered_html.find("div")
+ solution_element = rendered_html.xpath('//div[@class="input-template-render"]')[0]
self.assertEqual(solution_element.text, 'Input Template Render')
# Expect that the template renderer was called with the correct
@@ -218,9 +226,9 @@ class CapaHtmlRenderTest(unittest.TestCase):
"""
problem = new_loncapa_problem(xml)
rendered_html = etree.XML(problem.get_html())
- sections = rendered_html.findall('section')
- self.assertEqual(sections[0].attrib['aria-label'], 'Question 1')
- self.assertEqual(sections[1].attrib['aria-label'], 'Question 2')
+ response_elements = rendered_html.findall('div')
+ self.assertEqual(response_elements[0].attrib['aria-label'], 'Question 1')
+ self.assertEqual(response_elements[1].attrib['aria-label'], 'Question 2')
def test_render_response_with_overall_msg(self):
# CustomResponse script that sets an overall_message
diff --git a/common/lib/capa/capa/tests/test_input_templates.py b/common/lib/capa/capa/tests/test_input_templates.py
index 9c7ebf94ff..a4f8eae3dd 100644
--- a/common/lib/capa/capa/tests/test_input_templates.py
+++ b/common/lib/capa/capa/tests/test_input_templates.py
@@ -1181,3 +1181,43 @@ class SchematicInputTemplateTest(TemplateTestCase):
Verify aria-label attribute rendering.
"""
self.assert_label(aria_label=True)
+
+
+class CodeinputTemplateTest(TemplateTestCase):
+ """
+ Test mako template for `` input
+ """
+
+ TEMPLATE_NAME = 'codeinput.html'
+
+ def setUp(self):
+ super(CodeinputTemplateTest, self).setUp()
+ self.context = {
+ 'id': '1',
+ 'status': Status('correct'),
+ 'mode': 'parrot',
+ 'linenumbers': 'false',
+ 'rows': '37',
+ 'cols': '11',
+ 'tabsize': '7',
+ 'hidden': '',
+ 'msg': '',
+ 'value': 'print "good evening"',
+ 'aria_label': 'python editor',
+ 'code_mirror_exit_message': 'Press ESC then TAB or click outside of the code editor to exit',
+ 'response_data': self.RESPONSE_DATA,
+ 'describedby': self.DESCRIBEDBY,
+ }
+
+ def test_label(self):
+ """
+ Verify question label is rendered correctly.
+ """
+ self.assert_label(xpath="//label[@class='problem-group-label']")
+
+ def test_editor_exit_message(self):
+ """
+ Verify that editor exit message is rendered.
+ """
+ xml = self.render_to_xml(self.context)
+ self.assert_has_text(xml, '//span[@id="cm-editor-exit-message-1"]', self.context['code_mirror_exit_message'])
diff --git a/common/lib/capa/capa/tests/test_inputtypes.py b/common/lib/capa/capa/tests/test_inputtypes.py
index 01122c1df3..d94ab947ea 100644
--- a/common/lib/capa/capa/tests/test_inputtypes.py
+++ b/common/lib/capa/capa/tests/test_inputtypes.py
@@ -421,6 +421,8 @@ class CodeInputTest(unittest.TestCase):
'hidden': '',
'tabsize': int(tabsize),
'queue_len': '3',
+ 'aria_label': '{mode} editor'.format(mode=mode),
+ 'code_mirror_exit_message': 'Press ESC then TAB or click outside of the code editor to exit',
'response_data': RESPONSE_DATA,
'describedby_html': DESCRIBEDBY
}
diff --git a/common/lib/xmodule/xmodule/css/capa/display.scss b/common/lib/xmodule/xmodule/css/capa/display.scss
index fa263d09e3..2e45ff8af0 100644
--- a/common/lib/xmodule/xmodule/css/capa/display.scss
+++ b/common/lib/xmodule/xmodule/css/capa/display.scss
@@ -908,6 +908,12 @@ div.problem {
}
}
+.capa-message {
+ display: inline-block;
+ color: $gray-d1;
+ -webkit-font-smoothing: antialiased;
+}
+
// +Problem - Actions
// ====================
div.problem .action {
diff --git a/common/lib/xmodule/xmodule/js/fixtures/codeinput_problem.html b/common/lib/xmodule/xmodule/js/fixtures/codeinput_problem.html
new file mode 100644
index 0000000000..2f5992bac3
--- /dev/null
+++ b/common/lib/xmodule/xmodule/js/fixtures/codeinput_problem.html
@@ -0,0 +1,21 @@
+
+
+
write some awesome code
+
+ Press ESC then TAB or click outside of the code editor to exit
+
+
+