Commit c5627b41 by Dave St.Germain

Merge pull request #3002 from edx/dcs/status-object

Convert CAPA inputtype statuses from strings to objects,
parents ce9e8d73 bf7aef1b
...@@ -62,7 +62,47 @@ log = logging.getLogger(__name__) ...@@ -62,7 +62,47 @@ log = logging.getLogger(__name__)
######################################################################### #########################################################################
registry = TagRegistry() registry = TagRegistry() # pylint: disable=C0103
class Status(object):
"""
Problem status
attributes: classname, display_name
"""
css_classes = {
# status: css class
'unsubmitted': 'unanswered',
'incomplete': 'incorrect',
'queued': 'processing',
}
__slots__ = ('classname', '_status', 'display_name')
def __init__(self, status, gettext_func=unicode):
self.classname = self.css_classes.get(status, status)
_ = gettext_func
names = {
'correct': _('correct'),
'incorrect': _('incorrect'),
'incomplete': _('incomplete'),
'unanswered': _('unanswered'),
'unsubmitted': _('unanswered'),
'queued': _('processing'),
}
self.display_name = names.get(status, unicode(status))
self._status = status or ''
def __str__(self):
return self._status
def __unicode__(self):
return self._status.decode('utf8')
def __repr__(self):
return 'Status(%r)' % self._status
def __eq__(self, other):
return self._status == str(other)
class Attribute(object): class Attribute(object):
...@@ -261,9 +301,7 @@ class InputTypeBase(object): ...@@ -261,9 +301,7 @@ class InputTypeBase(object):
context = { context = {
'id': self.input_id, 'id': self.input_id,
'value': self.value, 'value': self.value,
'status': self.status, 'status': Status(self.status, self.capa_system.i18n.ugettext),
'status_class': self.status_class,
'status_display': self.status_display,
'msg': self.msg, 'msg': self.msg,
'STATIC_URL': self.capa_system.STATIC_URL, 'STATIC_URL': self.capa_system.STATIC_URL,
} }
...@@ -273,34 +311,6 @@ class InputTypeBase(object): ...@@ -273,34 +311,6 @@ class InputTypeBase(object):
context.update(self._extra_context()) context.update(self._extra_context())
return context return context
@property
def status_class(self):
"""
Return the CSS class for the associated status.
"""
statuses = {
'unsubmitted': 'unanswered',
'incomplete': 'incorrect',
'queued': 'processing',
}
return statuses.get(self.status, self.status)
@property
def status_display(self):
"""
Return the human-readable and translated word for the associated status.
"""
_ = self.capa_system.i18n.ugettext
statuses = {
'correct': _('correct'),
'incorrect': _('incorrect'),
'incomplete': _('incomplete'),
'unanswered': _('unanswered'),
'unsubmitted': _('unanswered'),
'queued': _('queued'),
}
return statuses.get(self.status, self.status)
def _extra_context(self): def _extra_context(self):
""" """
Subclasses can override this to return extra context that should be passed to their templates for rendering. Subclasses can override this to return extra context that should be passed to their templates for rendering.
......
...@@ -52,13 +52,7 @@ ...@@ -52,13 +52,7 @@
<input type="hidden" class="value" name="input_${id}" id="input_${id}" value="${value|h}" /> <input type="hidden" class="value" name="input_${id}" id="input_${id}" value="${value|h}" />
% endif % endif
% if status == 'unsubmitted': <span class="status ${status.classname}" id="status_${id}" aria-describedby="input_${id}"><span class="sr">${status.display_name}</span></span>
<span class="unanswered" style="display:inline-block;" id="status_${id}" aria-describedby="input_${id}"><span class="sr">Status: Unanswered</span></span>
% elif status == 'incomplete':
<span class="incorrect" id="status_${id}" aria-describedby="input_${id}"><span class="sr">Status: Incorrect</span></span>
% elif status == 'incorrect' and not has_options_value:
<span class="incorrect" id="status_${id}" aria-describedby="input_${id}"><span class="sr">Status: Incorrect</span></span>
% endif
<p id="answer_${id}" class="answer answer-annotation"></p> <p id="answer_${id}" class="answer answer-annotation"></p>
</div> </div>
......
<div id="chemicalequationinput_${id}" class="chemicalequationinput"> <div id="chemicalequationinput_${id}" class="chemicalequationinput">
<div class="script_placeholder" data-src="${previewer}"/> <div class="script_placeholder" data-src="${previewer}"/>
<div class="${status_class}" id="status_${id}"> <div class="${status.classname}" id="status_${id}">
<input type="text" name="input_${id}" id="input_${id}" aria-label="${label}" aria-describedby="answer_${id}" data-input-id="${id}" value="${value|h}" <input type="text" name="input_${id}" id="input_${id}" aria-label="${label}" aria-describedby="answer_${id}" data-input-id="${id}" value="${value|h}"
% if size: % if size:
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<p class="status" aria-describedby="input_${id}"> <p class="status" aria-describedby="input_${id}">
${value|h} - ${value|h} -
${status_display} ${status.display_name}
</p> </p>
<div id="input_${id}_preview" class="equation"></div> <div id="input_${id}_preview" class="equation"></div>
......
<form class="choicegroup capa_inputtype" id="inputtype_${id}"> <form class="choicegroup capa_inputtype" id="inputtype_${id}">
<div class="indicator_container"> <div class="indicator_container">
% if input_type == 'checkbox' or not value: % if input_type == 'checkbox' or not value:
<span class="status ${status_class if show_correctness != 'never' else 'unanswered'}" <span class="status ${status.classname if show_correctness != 'never' else 'unanswered'}"
id="status_${id}" id="status_${id}"
aria-describedby="inputtype_${id}"> aria-describedby="inputtype_${id}">
<span class="sr"> <span class="sr">
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
%endif %endif
%endfor %endfor
- -
${status_display} ${status.display_name}
</span> </span>
</span> </span>
% endif % endif
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
% if input_type == 'radio' and ( (isinstance(value, basestring) and (choice_id == value)) or (not isinstance(value, basestring) and choice_id in value) ): % if input_type == 'radio' and ( (isinstance(value, basestring) and (choice_id == value)) or (not isinstance(value, basestring) and choice_id in value) ):
% if status in ('correct', 'incorrect') and not show_correctness=='never': % if status in ('correct', 'incorrect') and not show_correctness=='never':
<span class="sr status">${choice_description|h} - ${status_display}</span> <span class="sr status">${choice_description|h} - ${status.display_name}</span>
% endif % endif
% endif % endif
</label> </label>
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<div class="script_placeholder" data-src="/static/js/capa/choicetextinput.js"/> <div class="script_placeholder" data-src="/static/js/capa/choicetextinput.js"/>
<div class="indicator_container"> <div class="indicator_container">
% if input_type == 'checkbox' or not element_checked: % if input_type == 'checkbox' or not element_checked:
<span class="status ${status_class}" id="status_${id}"></span> <span class="status ${status.classname}" id="status_${id}"></span>
% endif % endif
</div> </div>
......
...@@ -17,10 +17,10 @@ ...@@ -17,10 +17,10 @@
<div class="grader-status" tabindex="-1"> <div class="grader-status" tabindex="-1">
<span id="status_${id}" <span id="status_${id}"
class="${status_class}" class="${status.classname}"
aria-describedby="input_${id}" aria-describedby="input_${id}"
> >
<span class="status sr">${status_display}</span> <span class="status sr">${status.display_name}</span>
</span> </span>
% if status == 'queued': % if status == 'queued':
<span style="display:none;" class="xqueue" id="${id}">${queue_len}</span> <span style="display:none;" class="xqueue" id="${id}">${queue_len}</span>
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
<div style="display:none;" name="${hidden}" inputid="input_${id}" /> <div style="display:none;" name="${hidden}" inputid="input_${id}" />
% endif % endif
<p class="debug">${status_display}</p> <p class="debug">${status.display_name}</p>
</div> </div>
<span id="answer_${id}"></span> <span id="answer_${id}"></span>
......
...@@ -9,29 +9,14 @@ ...@@ -9,29 +9,14 @@
<div class="script_placeholder" data-src="/static/js/sylvester.js"></div> <div class="script_placeholder" data-src="/static/js/sylvester.js"></div>
<div class="script_placeholder" data-src="/static/js/crystallography.js"></div> <div class="script_placeholder" data-src="/static/js/crystallography.js"></div>
% if status == 'unsubmitted': % if status in ['unsubmitted', 'correct', 'incorrect', 'incomplete']:
<div class="unanswered" id="status_${id}"> <div class="status ${status.classname}" id="status_${id}">
% elif status == 'correct':
<div class="correct" id="status_${id}">
% elif status == 'incorrect':
<div class="incorrect" id="status_${id}">
% elif status == 'incomplete':
<div class="incorrect" id="status_${id}">
% endif
<input type="text" name="input_${id}" aria-describedby="answer_${id}" id="input_${id}" value="${value|h}" style="display:none;"/> <input type="text" name="input_${id}" aria-describedby="answer_${id}" id="input_${id}" value="${value|h}" style="display:none;"/>
<p class="status" aria-describedby="input_${id}"> <p class="status" aria-describedby="input_${id}">
% if status == 'unsubmitted': ${status.display_name}
unanswered
% elif status == 'correct':
correct
% elif status == 'incorrect':
incorrect
% elif status == 'incomplete':
incomplete
% endif
</p> </p>
<p id="answer_${id}" class="answer"></p> <p id="answer_${id}" class="answer"></p>
......
...@@ -2,14 +2,8 @@ ...@@ -2,14 +2,8 @@
<div class="script_placeholder" data-src="/static/js/capa/protex/protex.nocache.js?raw"/> <div class="script_placeholder" data-src="/static/js/capa/protex/protex.nocache.js?raw"/>
<div class="script_placeholder" data-src="${applet_loader}"/> <div class="script_placeholder" data-src="${applet_loader}"/>
% if status == 'unsubmitted': % if status in ['unsubmitted', 'correct', 'incorrect', 'incomplete']:
<div class="unanswered" id="status_${id}"> <div class="${status.classname}" id="status_${id}">
% elif status == 'correct':
<div class="correct" id="status_${id}">
% elif status == 'incorrect':
<div class="incorrect" id="status_${id}">
% elif status == 'incomplete':
<div class="incomplete" id="status_${id}">
% endif % endif
<div id="protex_container"></div> <div id="protex_container"></div>
...@@ -17,15 +11,7 @@ ...@@ -17,15 +11,7 @@
<input type="hidden" name="input_${id}" id="input_${id}" aria-describedby="answer_${id}" value="${value|h}"/> <input type="hidden" name="input_${id}" id="input_${id}" aria-describedby="answer_${id}" value="${value|h}"/>
<p class="status" aria-describedby="input_${id}"> <p class="status" aria-describedby="input_${id}">
% if status == 'unsubmitted': ${status.display_name}
unanswered
% elif status == 'correct':
correct
% elif status == 'incorrect':
incorrect
% elif status == 'incomplete':
incomplete
% endif
</p> </p>
<p id="answer_${id}" class="answer"></p> <p id="answer_${id}" class="answer"></p>
......
...@@ -8,14 +8,8 @@ ...@@ -8,14 +8,8 @@
<div class="script_placeholder" data-src="${STATIC_URL}js/capa/drag_and_drop.js"></div> <div class="script_placeholder" data-src="${STATIC_URL}js/capa/drag_and_drop.js"></div>
% if status == 'unsubmitted': % if status in ['unsubmitted', 'correct', 'incorrect', 'incomplete']:
<div class="unanswered" id="status_${id}"> <div class="${status.classname}" id="status_${id}">
% elif status == 'correct':
<div class="correct" id="status_${id}">
% elif status == 'incorrect':
<div class="incorrect" id="status_${id}">
% elif status == 'incomplete':
<div class="incorrect" id="status_${id}">
% endif % endif
...@@ -23,15 +17,7 @@ ...@@ -23,15 +17,7 @@
style="display:none;"/> style="display:none;"/>
<p class="status" aria-describedby="input_${id}"> <p class="status" aria-describedby="input_${id}">
% if status == 'unsubmitted': ${status.display_name}
unanswered
% elif status == 'correct':
correct
% elif status == 'incorrect':
incorrect
% elif status == 'incomplete':
incomplete
% endif
</p> </p>
<p id="answer_${id}" class="answer"></p> <p id="answer_${id}" class="answer"></p>
......
...@@ -2,14 +2,8 @@ ...@@ -2,14 +2,8 @@
<div class="script_placeholder" data-src="/static/js/capa/genex/genex.nocache.js?raw"/> <div class="script_placeholder" data-src="/static/js/capa/genex/genex.nocache.js?raw"/>
<div class="script_placeholder" data-src="${applet_loader}"/> <div class="script_placeholder" data-src="${applet_loader}"/>
% if status == 'unsubmitted': % if status in ['unsubmitted', 'correct', 'incorrect', 'incomplete']:
<div class="unanswered" id="status_${id}"> <div class="${status.classname}" id="status_${id}">
% elif status == 'correct':
<div class="correct" id="status_${id}">
% elif status == 'incorrect':
<div class="incorrect" id="status_${id}">
% elif status == 'incomplete':
<div class="incomplete" id="status_${id}">
% endif % endif
<div id="genex_container"></div> <div id="genex_container"></div>
...@@ -18,15 +12,7 @@ ...@@ -18,15 +12,7 @@
<input type="hidden" name="input_${id}" aria-describedby="answer_${id}" id="input_${id}" value="${value|h}"/> <input type="hidden" name="input_${id}" aria-describedby="answer_${id}" id="input_${id}" value="${value|h}"/>
<p class="status" aria-describedby="input_${id}"> <p class="status" aria-describedby="input_${id}">
% if status == 'unsubmitted': ${status.display_name}
unanswered
% elif status == 'correct':
correct
% elif status == 'incorrect':
incorrect
% elif status == 'incomplete':
incomplete
% endif
</p> </p>
<p id="answer_${id}" class="answer"></p> <p id="answer_${id}" class="answer"></p>
......
<section id="editamoleculeinput_${id}" class="editamoleculeinput"> <section id="editamoleculeinput_${id}" class="editamoleculeinput">
<div class="script_placeholder" data-src="${applet_loader}"/> <div class="script_placeholder" data-src="${applet_loader}"/>
% if status == 'unsubmitted': % if status in ['unsubmitted', 'correct', 'incorrect', 'incomplete']:
<div class="unanswered" id="status_${id}"> <div class="${status.classname}" id="status_${id}">
% elif status == 'correct':
<div class="correct" id="status_${id}">
% elif status == 'incorrect':
<div class="incorrect" id="status_${id}">
% elif status == 'incomplete':
<div class="incorrect" id="status_${id}">
% endif % endif
<div id="applet_${id}" class="applet" data-molfile-src="${file}" style="display:block;width:500px;height:400px"> <div id="applet_${id}" class="applet" data-molfile-src="${file}" style="display:block;width:500px;height:400px">
...@@ -23,15 +17,7 @@ ...@@ -23,15 +17,7 @@
<p id="answer_${id}" class="answer"></p> <p id="answer_${id}" class="answer"></p>
<p class="status" aria-describedby="input_${id}"> <p class="status" aria-describedby="input_${id}">
% if status == 'unsubmitted': ${status.display_name}
unanswered
% elif status == 'correct':
correct
% elif status == 'incorrect':
incorrect
% elif status == 'incomplete':
incomplete
% endif
</p> </p>
<br/> <br/> <br/> <br/>
......
<section id="filesubmission_${id}" class="filesubmission"> <section id="filesubmission_${id}" class="filesubmission">
<div class="grader-status file"> <div class="grader-status file">
% if status == 'unsubmitted':
<span class="unanswered" style="display:inline-block;" id="status_${id}">Unanswered</span> <span class="${status.classname}" id="status_${id}">${status.display_name}</span>
% elif status == 'correct': % if status == 'queued':
<span class="correct" id="status_${id}">Correct</span> <span style="display:none;" class="xqueue" id="${id}">${queue_len}</span>
% elif status == 'incorrect':
<span class="incorrect" id="status_${id}">Incorrect</span>
% elif status == 'queued':
<span class="processing" id="status_${id}">Queued</span>
<span style="display:none;" class="xqueue" id="${id}" >${queue_len}</span>
% endif % endif
<p class="debug">${status}</p> <p class="debug">${status}</p>
......
<% doinline = 'style="display:inline-block;vertical-align:top"' if inline else "" %> <% doinline = 'style="display:inline-block;vertical-align:top"' if inline else "" %>
<section id="formulaequationinput_${id}" class="inputtype formulaequationinput" ${doinline}> <section id="formulaequationinput_${id}" class="inputtype formulaequationinput" ${doinline}>
<div class="${status_class}" id="status_${id}"> <div class="${status.classname}" id="status_${id}">
<input type="text" name="input_${id}" id="input_${id}" <input type="text" name="input_${id}" id="input_${id}"
data-input-id="${id}" value="${value|h}" data-input-id="${id}" value="${value|h}"
aria-label="${label}" aria-label="${label}"
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
% else: % else:
${label} ${label}
%endif %endif
</span> - ${status_display} </span> - ${status.display_name}
</p> </p>
<div id="input_${id}_preview" class="equation"> <div id="input_${id}_preview" class="equation">
......
...@@ -39,38 +39,11 @@ ...@@ -39,38 +39,11 @@
(new ImageInput('${id}')); (new ImageInput('${id}'));
</script> </script>
% if status == 'unsubmitted':
<span <span
class="unanswered" class="status ${status.classname}"
style="display: inline-block;"
id="status_${id}" id="status_${id}"
aria-describedby="input_${id}" aria-describedby="input_${id}"
> >
<span class="sr">Status: unanswered</span> <span class="sr">${status.display_name}</span>
</span> </span>
% elif status == 'correct':
<span
class="correct"
id="status_${id}"
aria-describedby="input_${id}"
>
<span class="sr">Status: correct</span>
</span>
% elif status == 'incorrect':
<span
class="incorrect"
id="status_${id}"
aria-describedby="input_${id}"
>
<span class="sr">Status: incorrect</span>
</span>
% elif status == 'incomplete':
<span
class="incorrect"
id="status_${id}"
aria-describedby="input_${id}"
>
<span class="sr">Status: incorrect</span>
</span>
% endif
</div> </div>
...@@ -17,14 +17,8 @@ ...@@ -17,14 +17,8 @@
<div class="script_placeholder" data-src="${jschannel_loader}"/> <div class="script_placeholder" data-src="${jschannel_loader}"/>
<div class="script_placeholder" data-src="${jsinput_loader}"/> <div class="script_placeholder" data-src="${jsinput_loader}"/>
% if status == 'unsubmitted': % if status in ['unsubmitted', 'correct', 'incorrect', 'incomplete']:
<div class="unanswered" id="status_${id}"> <div class="${status.classname}" id="status_${id}">
% elif status == 'correct':
<div class="correct" id="status_${id}">
% elif status == 'incorrect':
<div class="incorrect" id="status_${id}">
% elif status == 'incomplete':
<div class="incorrect" id="status_${id}">
% endif % endif
<iframe name="iframe_${id}" <iframe name="iframe_${id}"
...@@ -44,15 +38,7 @@ ...@@ -44,15 +38,7 @@
<p id="answer_${id}" class="answer"></p> <p id="answer_${id}" class="answer"></p>
<p class="status"> <p class="status">
% if status == 'unsubmitted': ${status.display_name}
unanswered
% elif status == 'correct':
correct
% elif status == 'incorrect':
incorrect
% elif status == 'incomplete':
incomplete
% endif
</p> </p>
<br/> <br/> <br/> <br/>
......
...@@ -18,23 +18,9 @@ ...@@ -18,23 +18,9 @@
<textarea style="display:none" id="input_${id}_fromjs" name="input_${id}_fromjs"></textarea> <textarea style="display:none" id="input_${id}_fromjs" name="input_${id}_fromjs"></textarea>
% endif % endif
% if status == 'unsubmitted': <span class="status ${status.classname}" id="status_${id}" aria-describedby="input_${id}">
<span class="unanswered" style="display:inline-block;" id="status_${id}" aria-describedby="input_${id}"> <span class="sr">${status.display_name</span>
<span class="sr">Status: unanswered</span>
</span> </span>
% elif status == 'correct':
<span class="correct" id="status_${id}" aria-describedby="input_${id}">
<span class="sr">Status: correct</span>
</span>
% elif status == 'incorrect':
<span class="incorrect" id="status_${id}" aria-describedby="input_${id}">
<span class="sr">Status: incorrect</span>
</span>
% elif status == 'incomplete':
<span class="incorrect" id="status_${id}" aria-describedby="input_${id}">
<span class="sr">Status: incorrect</span>
</span>
% endif
% if msg: % if msg:
<br/> <br/>
<span class="debug">${msg|n}</span> <span class="debug">${msg|n}</span>
......
...@@ -18,10 +18,10 @@ ...@@ -18,10 +18,10 @@
<div class="grader-status" tabindex="-1"> <div class="grader-status" tabindex="-1">
<span id="status_${id}" <span id="status_${id}"
class="${status_class}" class="${status.classname}"
aria-describedby="input_${id}" aria-describedby="input_${id}"
> >
<span class="status sr">${status_display}</span> <span class="status sr">${status.display_name}</span>
</span> </span>
% if status == 'queued': % if status == 'queued':
<span style="display:none;" class="xqueue" id="${id}">${queue_len}</span> <span style="display:none;" class="xqueue" id="${id}">${queue_len}</span>
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
<div style="display:none;" name="${hidden}" inputid="input_${id}" /> <div style="display:none;" name="${hidden}" inputid="input_${id}" />
% endif % endif
<p class="debug">${status_display}</p> <p class="debug">${status.display_name}</p>
</div> </div>
<span id="answer_${id}"></span> <span id="answer_${id}"></span>
......
...@@ -13,10 +13,10 @@ ...@@ -13,10 +13,10 @@
</select> </select>
<span id="answer_${id}"></span> <span id="answer_${id}"></span>
<span class="status ${status_class}" <span class="status ${status.classname}"
id="status_${id}" id="status_${id}"
aria-describedby="input_${id}"> aria-describedby="input_${id}">
<span class="sr">${value|h} - ${status_display}</span> <span class="sr">${value|h} - ${status.display_name}</span>
</span> </span>
% if msg: % if msg:
......
<span> <div>
<div class="script_placeholder" data-src="${setup_script}"/> <div class="script_placeholder" data-src="${setup_script}"/>
<input type="hidden" <input type="hidden"
class="schematic" class="schematic"
...@@ -16,23 +16,7 @@ ...@@ -16,23 +16,7 @@
/> />
<span id="answer_${id}"></span> <span id="answer_${id}"></span>
% if status == 'unsubmitted': <span class="status ${status.classname}" id="status_${id}" aria-describedby="input_${id}">
<span class="ui-icon ui-icon-bullet" style="display:inline-block;" id="status_${id}" aria-describedby="input_${id}"> <span class="sr">${status.display_name}</span>
<span class="sr">Status: unsubmitted</span>
</span> </span>
% elif status == 'correct': </div>
<span class="ui-icon ui-icon-check" style="display:inline-block;" id="status_${id}" aria-describedby="input_${id}">
<span class="sr">Status: correct</span>
</span>
% elif status == 'incorrect':
<span class="ui-icon ui-icon-close" style="display:inline-block;" id="status_${id}" aria-describedby="input_${id}">
<span class="sr">Status: incorrect</span>
</span>
% elif status == 'incomplete':
<span class="ui-icon ui-icon-close" style="display:inline-block;" id="status_${id}" aria-describedby="input_${id}">
<span class="sr">Status: incomplete</span>
</span>
% endif
</span>
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
% endif % endif
% if status in ('unsubmitted', 'correct', 'incorrect', 'incomplete'): % if status in ('unsubmitted', 'correct', 'incorrect', 'incomplete'):
<div class="${status_class} ${doinline}" id="status_${id}"> <div class="${status.classname} ${doinline}" id="status_${id}">
% endif % endif
% if hidden: % if hidden:
<div style="display:none;" name="${hidden}" inputid="input_${id}" /> <div style="display:none;" name="${hidden}" inputid="input_${id}" />
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
${label} ${label}
%endif %endif
- -
${status_display} ${status.display_name}
</p> </p>
<p id="answer_${id}" class="answer" aria-hidden="true"></p> <p id="answer_${id}" class="answer" aria-hidden="true"></p>
......
...@@ -11,14 +11,8 @@ ...@@ -11,14 +11,8 @@
<div class="script_placeholder" data-src="/static/js/vsepr/vsepr.js"></div> <div class="script_placeholder" data-src="/static/js/vsepr/vsepr.js"></div>
% if status == 'unsubmitted': % if status in ['unsubmitted', 'correct', 'incorrect', 'incomplete']:
<div class="unanswered" id="status_${id}"> <div class="${status.classname}" id="status_${id}">
% elif status == 'correct':
<div class="correct" id="status_${id}">
% elif status == 'incorrect':
<div class="incorrect" id="status_${id}">
% elif status == 'incomplete':
<div class="incorrect" id="status_${id}">
% endif % endif
<input type="text" name="input_${id}" id="input_${id}" aria-describedby="answer_${id}" value="${value|h}" <input type="text" name="input_${id}" id="input_${id}" aria-describedby="answer_${id}" value="${value|h}"
...@@ -26,15 +20,7 @@ ...@@ -26,15 +20,7 @@
/> />
<p class="status" aria-describedby="input_${id}"> <p class="status" aria-describedby="input_${id}">
% if status == 'unsubmitted': ${status.display_name}
unanswered
% elif status == 'correct':
correct
% elif status == 'incorrect':
incorrect
% elif status == 'incomplete':
incomplete
% endif
</p> </p>
<p id="answer_${id}" class="answer"></p> <p id="answer_${id}" class="answer"></p>
......
...@@ -7,6 +7,7 @@ import os.path ...@@ -7,6 +7,7 @@ import os.path
import fs.osfs import fs.osfs
from capa.capa_problem import LoncapaProblem, LoncapaSystem from capa.capa_problem import LoncapaProblem, LoncapaSystem
from capa.inputtypes import Status
from mock import Mock, MagicMock from mock import Mock, MagicMock
import xml.sax.saxutils as saxutils import xml.sax.saxutils as saxutils
...@@ -47,6 +48,7 @@ def test_capa_system(): ...@@ -47,6 +48,7 @@ def test_capa_system():
render_template=tst_render_template, render_template=tst_render_template,
seed=0, seed=0,
STATIC_URL='/dummy-static/', STATIC_URL='/dummy-static/',
STATUS_CLASS=Status,
xqueue={'interface': xqueue_interface, 'construct_callback': calledback_url, 'default_queuename': 'testqueue', 'waittime': 10}, xqueue={'interface': xqueue_interface, 'construct_callback': calledback_url, 'default_queuename': 'testqueue', 'waittime': 10},
) )
return the_system return the_system
......
...@@ -153,9 +153,7 @@ class CapaHtmlRenderTest(unittest.TestCase): ...@@ -153,9 +153,7 @@ class CapaHtmlRenderTest(unittest.TestCase):
# the solution # the solution
expected_textline_context = { expected_textline_context = {
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'status': 'unsubmitted', 'status': the_system.STATUS_CLASS('unsubmitted'),
'status_class': 'unanswered',
'status_display': u'unanswered',
'label': '', 'label': '',
'value': '', 'value': '',
'preprocessor': None, 'preprocessor': None,
......
...@@ -9,7 +9,7 @@ import json ...@@ -9,7 +9,7 @@ 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
from capa.inputtypes import Status
class TemplateError(Exception): class TemplateError(Exception):
""" """
...@@ -123,9 +123,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase): ...@@ -123,9 +123,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
choices = [('1', 'choice 1'), ('2', 'choice 2'), ('3', 'choice 3')] choices = [('1', 'choice 1'), ('2', 'choice 2'), ('3', 'choice 3')]
self.context = {'id': '1', self.context = {'id': '1',
'choices': choices, 'choices': choices,
'status': 'correct', 'status': Status('correct'),
'status_class': 'correct',
'status_display': u'correct',
'label': 'test', 'label': 'test',
'input_type': 'checkbox', 'input_type': 'checkbox',
'name_array_suffix': '1', 'name_array_suffix': '1',
...@@ -138,7 +136,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase): ...@@ -138,7 +136,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
(not a particular option) is marked correct. (not a particular option) is marked correct.
""" """
self.context['status'] = self.context['status_class'] = self.context['status_display'] = 'correct' self.context['status'] = Status('correct')
self.context['input_type'] = 'checkbox' self.context['input_type'] = 'checkbox'
self.context['value'] = ['1', '2'] self.context['value'] = ['1', '2']
...@@ -160,14 +158,14 @@ class ChoiceGroupTemplateTest(TemplateTestCase): ...@@ -160,14 +158,14 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
(not a particular option) is marked incorrect. (not a particular option) is marked incorrect.
""" """
conditions = [ conditions = [
{'status': 'incorrect', 'input_type': 'radio', 'value': '', 'status_class': 'incorrect'}, {'status': Status('incorrect'), 'input_type': 'radio', 'value': ''},
{'status': 'incorrect', 'input_type': 'checkbox', 'value': [], 'status_class': 'incorrect'}, {'status': Status('incorrect'), 'input_type': 'checkbox', 'value': []},
{'status': 'incorrect', 'input_type': 'checkbox', 'value': ['2'], 'status_class': 'incorrect'}, {'status': Status('incorrect'), 'input_type': 'checkbox', 'value': ['2']},
{'status': 'incorrect', 'input_type': 'checkbox', 'value': ['2', '3'], 'status_class': 'incorrect'}, {'status': Status('incorrect'), 'input_type': 'checkbox', 'value': ['2', '3']},
{'status': 'incomplete', 'input_type': 'radio', 'value': '', 'status_class': 'incorrect'}, {'status': Status('incomplete'), 'input_type': 'radio', 'value': ''},
{'status': 'incomplete', 'input_type': 'checkbox', 'value': [], 'status_class': 'incorrect'}, {'status': Status('incomplete'), 'input_type': 'checkbox', 'value': []},
{'status': 'incomplete', 'input_type': 'checkbox', 'value': ['2'], 'status_class': 'incorrect'}, {'status': Status('incomplete'), 'input_type': 'checkbox', 'value': ['2']},
{'status': 'incomplete', 'input_type': 'checkbox', 'value': ['2', '3'], 'status_class': 'incorrect'}] {'status': Status('incomplete'), 'input_type': 'checkbox', 'value': ['2', '3']}]
for test_conditions in conditions: for test_conditions in conditions:
self.context.update(test_conditions) self.context.update(test_conditions)
...@@ -190,16 +188,16 @@ class ChoiceGroupTemplateTest(TemplateTestCase): ...@@ -190,16 +188,16 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
(not a particular option) is marked unanswered. (not a particular option) is marked unanswered.
""" """
conditions = [ conditions = [
{'status': 'unsubmitted', 'input_type': 'radio', 'value': '', 'status_class': 'unanswered'}, {'status': Status('unsubmitted'), 'input_type': 'radio', 'value': ''},
{'status': 'unsubmitted', 'input_type': 'radio', 'value': [], 'status_class': 'unanswered'}, {'status': Status('unsubmitted'), 'input_type': 'radio', 'value': []},
{'status': 'unsubmitted', 'input_type': 'checkbox', 'value': [], 'status_class': 'unanswered'}, {'status': Status('unsubmitted'), 'input_type': 'checkbox', 'value': []},
{'input_type': 'radio', 'value': ''}, {'input_type': 'radio', 'value': ''},
{'input_type': 'radio', 'value': []}, {'input_type': 'radio', 'value': []},
{'input_type': 'checkbox', 'value': []}, {'input_type': 'checkbox', 'value': []},
{'input_type': 'checkbox', 'value': ['1']}, {'input_type': 'checkbox', 'value': ['1']},
{'input_type': 'checkbox', 'value': ['1', '2']}] {'input_type': 'checkbox', 'value': ['1', '2']}]
self.context['status'] = self.context['status_class'] = 'unanswered' self.context['status'] = Status('unanswered')
for test_conditions in conditions: for test_conditions in conditions:
self.context.update(test_conditions) self.context.update(test_conditions)
...@@ -225,7 +223,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase): ...@@ -225,7 +223,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
{'input_type': 'radio', 'value': '2'}, {'input_type': 'radio', 'value': '2'},
{'input_type': 'radio', 'value': ['2']}] {'input_type': 'radio', 'value': ['2']}]
self.context['status'] = 'correct' self.context['status'] = Status('correct')
for test_conditions in conditions: for test_conditions in conditions:
self.context.update(test_conditions) self.context.update(test_conditions)
...@@ -246,7 +244,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase): ...@@ -246,7 +244,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
{'input_type': 'radio', 'value': '2'}, {'input_type': 'radio', 'value': '2'},
{'input_type': 'radio', 'value': ['2']}] {'input_type': 'radio', 'value': ['2']}]
self.context['status'] = self.context['status_class'] = 'incorrect' self.context['status'] = Status('incorrect')
for test_conditions in conditions: for test_conditions in conditions:
self.context.update(test_conditions) self.context.update(test_conditions)
...@@ -270,16 +268,16 @@ class ChoiceGroupTemplateTest(TemplateTestCase): ...@@ -270,16 +268,16 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
""" """
conditions = [ conditions = [
{'input_type': 'radio', 'status': 'correct', 'value': '', 'status_class': 'correct'}, {'input_type': 'radio', 'status': Status('correct'), 'value': ''},
{'input_type': 'radio', 'status': 'correct', 'value': '2', 'status_class': 'correct'}, {'input_type': 'radio', 'status': Status('correct'), 'value': '2'},
{'input_type': 'radio', 'status': 'correct', 'value': ['2'], 'status_class': 'correct'}, {'input_type': 'radio', 'status': Status('correct'), 'value': ['2']},
{'input_type': 'radio', 'status': 'incorrect', 'value': '2', 'status_class': 'incorrect'}, {'input_type': 'radio', 'status': Status('incorrect'), 'value': '2'},
{'input_type': 'radio', 'status': 'incorrect', 'value': [], 'status_class': 'incorrect'}, {'input_type': 'radio', 'status': Status('incorrect'), 'value': []},
{'input_type': 'radio', 'status': 'incorrect', 'value': ['2'], 'status_class': 'incorrect'}, {'input_type': 'radio', 'status': Status('incorrect'), 'value': ['2']},
{'input_type': 'checkbox', 'status': 'correct', 'value': [], 'status_class': 'correct'}, {'input_type': 'checkbox', 'status': Status('correct'), 'value': []},
{'input_type': 'checkbox', 'status': 'correct', 'value': ['2'], 'status_class': 'correct'}, {'input_type': 'checkbox', 'status': Status('correct'), 'value': ['2']},
{'input_type': 'checkbox', 'status': 'incorrect', 'value': [], 'status_class': 'incorrect'}, {'input_type': 'checkbox', 'status': Status('incorrect'), 'value': []},
{'input_type': 'checkbox', 'status': 'incorrect', 'value': ['2'], 'status_class': 'incorrect'}] {'input_type': 'checkbox', 'status': Status('incorrect'), 'value': ['2']}]
self.context['show_correctness'] = 'never' self.context['show_correctness'] = 'never'
self.context['submitted_message'] = 'Test message' self.context['submitted_message'] = 'Test message'
...@@ -315,9 +313,9 @@ class ChoiceGroupTemplateTest(TemplateTestCase): ...@@ -315,9 +313,9 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
""" """
conditions = [ conditions = [
{'input_type': 'radio', 'status': 'unsubmitted', 'value': ''}, {'input_type': 'radio', 'status': Status('unsubmitted'), 'value': ''},
{'input_type': 'radio', 'status': 'unsubmitted', 'value': []}, {'input_type': 'radio', 'status': Status('unsubmitted'), 'value': []},
{'input_type': 'checkbox', 'status': 'unsubmitted', 'value': []}, {'input_type': 'checkbox', 'status': Status('unsubmitted'), 'value': []},
# These tests expose bug #365 # These tests expose bug #365
# When the bug is fixed, uncomment these cases. # When the bug is fixed, uncomment these cases.
...@@ -354,9 +352,7 @@ class TextlineTemplateTest(TemplateTestCase): ...@@ -354,9 +352,7 @@ class TextlineTemplateTest(TemplateTestCase):
def setUp(self): def setUp(self):
self.context = {'id': '1', self.context = {'id': '1',
'status': 'correct', 'status': Status('correct'),
'status_class': 'correct',
'status_display': u'correct',
'label': 'test', 'label': 'test',
'value': '3', 'value': '3',
'preprocessor': None, 'preprocessor': None,
...@@ -383,9 +379,7 @@ class TextlineTemplateTest(TemplateTestCase): ...@@ -383,9 +379,7 @@ class TextlineTemplateTest(TemplateTestCase):
('incomplete', 'incorrect', 'incomplete')] ('incomplete', 'incorrect', 'incomplete')]
for (context_status, div_class, status_mark) in cases: for (context_status, div_class, status_mark) in cases:
self.context['status'] = context_status self.context['status'] = Status(context_status)
self.context['status_class'] = div_class
self.context['status_display'] = status_mark
xml = self.render_to_xml(self.context) xml = self.render_to_xml(self.context)
# Expect that we get a <div> with correct class # Expect that we get a <div> with correct class
...@@ -461,8 +455,7 @@ class TextlineTemplateTest(TemplateTestCase): ...@@ -461,8 +455,7 @@ class TextlineTemplateTest(TemplateTestCase):
self.context['inline'] = True self.context['inline'] = True
for (context_status, div_class) in cases: for (context_status, div_class) in cases:
self.context['status'] = context_status self.context['status'] = Status(context_status)
self.context['status_class'] = div_class
xml = self.render_to_xml(self.context) xml = self.render_to_xml(self.context)
# Expect that we get a <div> with correct class # Expect that we get a <div> with correct class
...@@ -487,9 +480,7 @@ class FormulaEquationInputTemplateTest(TemplateTestCase): ...@@ -487,9 +480,7 @@ class FormulaEquationInputTemplateTest(TemplateTestCase):
self.context = { self.context = {
'id': 2, 'id': 2,
'value': 'PREFILLED_VALUE', 'value': 'PREFILLED_VALUE',
'status': 'unsubmitted', 'status': Status('unsubmitted'),
'status_class': 'unanswered',
'status_display': u'unsubmitted',
'label': 'test', 'label': 'test',
'previewer': 'file.js', 'previewer': 'file.js',
'reported_status': 'REPORTED_STATUS', 'reported_status': 'REPORTED_STATUS',
...@@ -525,9 +516,7 @@ class AnnotationInputTemplateTest(TemplateTestCase): ...@@ -525,9 +516,7 @@ class AnnotationInputTemplateTest(TemplateTestCase):
'options': [], 'options': [],
'has_options_value': False, 'has_options_value': False,
'debug': False, 'debug': False,
'status': 'unsubmitted', 'status': Status('unsubmitted'),
'status_class': 'unanswered',
'status_display': u'unsubmitted',
'return_to_annotation': False, 'return_to_annotation': False,
'msg': '<p>This is a test message</p>', } 'msg': '<p>This is a test message</p>', }
super(AnnotationInputTemplateTest, self).setUp() super(AnnotationInputTemplateTest, self).setUp()
...@@ -587,16 +576,16 @@ class AnnotationInputTemplateTest(TemplateTestCase): ...@@ -587,16 +576,16 @@ class AnnotationInputTemplateTest(TemplateTestCase):
('incorrect', 'incorrect')] ('incorrect', 'incorrect')]
for (input_status, expected_css_class) in test_cases: for (input_status, expected_css_class) in test_cases:
self.context['status'] = input_status self.context['status'] = Status(input_status)
xml = self.render_to_xml(self.context) xml = self.render_to_xml(self.context)
xpath = "//span[@class='{0}']".format(expected_css_class) xpath = "//span[@class='status {0}']".format(expected_css_class)
self.assert_has_xpath(xml, xpath, self.context) self.assert_has_xpath(xml, xpath, self.context)
# If individual options are being marked, then expect # If individual options are being marked, then expect
# just the option to be marked incorrect, not the whole problem # just the option to be marked incorrect, not the whole problem
self.context['has_options_value'] = True self.context['has_options_value'] = True
self.context['status'] = 'incorrect' self.context['status'] = Status('incorrect')
xpath = "//span[@class='incorrect']" xpath = "//span[@class='incorrect']"
xml = self.render_to_xml(self.context) xml = self.render_to_xml(self.context)
self.assert_no_xpath(xml, xpath, self.context) self.assert_no_xpath(xml, xpath, self.context)
...@@ -687,9 +676,7 @@ class OptionInputTemplateTest(TemplateTestCase): ...@@ -687,9 +676,7 @@ class OptionInputTemplateTest(TemplateTestCase):
self.context = { self.context = {
'id': 2, 'id': 2,
'options': [], 'options': [],
'status': 'unsubmitted', 'status': Status('unsubmitted'),
'status_class': 'unanswered',
'status_display': u'unanswered',
'label': 'test', 'label': 'test',
'value': 0 'value': 0
} }
...@@ -729,8 +716,7 @@ class OptionInputTemplateTest(TemplateTestCase): ...@@ -729,8 +716,7 @@ class OptionInputTemplateTest(TemplateTestCase):
('incomplete', 'status incorrect')] ('incomplete', 'status incorrect')]
for (input_status, expected_css_class) in test_cases: for (input_status, expected_css_class) in test_cases:
self.context['status'] = input_status self.context['status'] = Status(input_status)
self.context['status_class'] = expected_css_class.split(' ')[1]
xml = self.render_to_xml(self.context) xml = self.render_to_xml(self.context)
xpath = "//span[@class='{0}']".format(expected_css_class) xpath = "//span[@class='{0}']".format(expected_css_class)
...@@ -753,7 +739,7 @@ class DragAndDropTemplateTest(TemplateTestCase): ...@@ -753,7 +739,7 @@ class DragAndDropTemplateTest(TemplateTestCase):
self.context = {'id': 2, self.context = {'id': 2,
'drag_and_drop_json': '', 'drag_and_drop_json': '',
'value': 0, 'value': 0,
'status': 'unsubmitted', 'status': Status('unsubmitted'),
'msg': ''} 'msg': ''}
super(DragAndDropTemplateTest, self).setUp() super(DragAndDropTemplateTest, self).setUp()
...@@ -767,7 +753,7 @@ class DragAndDropTemplateTest(TemplateTestCase): ...@@ -767,7 +753,7 @@ class DragAndDropTemplateTest(TemplateTestCase):
('incomplete', 'incorrect', 'incomplete')] ('incomplete', 'incorrect', 'incomplete')]
for (input_status, expected_css_class, expected_text) in test_cases: for (input_status, expected_css_class, expected_text) in test_cases:
self.context['status'] = input_status self.context['status'] = Status(input_status)
xml = self.render_to_xml(self.context) xml = self.render_to_xml(self.context)
# Expect a <div> with the status # Expect a <div> with the status
...@@ -814,9 +800,7 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase): ...@@ -814,9 +800,7 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase):
{'tail_text': '', 'type': 'textinput', 'value': '', 'contents': 'choiceinput_1_textinput_0'}])] {'tail_text': '', 'type': 'textinput', 'value': '', 'contents': 'choiceinput_1_textinput_0'}])]
self.context = {'id': '1', self.context = {'id': '1',
'choices': choices, 'choices': choices,
'status': 'correct', 'status': Status('correct'),
'status_class': 'correct',
'status_display': u'correct',
'input_type': 'radio', 'input_type': 'radio',
'label': 'choicetext label', 'label': 'choicetext label',
'value': self.VALUE_DICT} 'value': self.VALUE_DICT}
...@@ -829,7 +813,7 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase): ...@@ -829,7 +813,7 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase):
Section is used for checkbox, so inputting text does not deselect Section is used for checkbox, so inputting text does not deselect
""" """
input_tags = ('radio', 'checkbox') input_tags = ('radio', 'checkbox')
self.context['status'] = 'correct' self.context['status'] = Status('correct')
xpath = "//section[@id='forinput1_choiceinput_0bc']" xpath = "//section[@id='forinput1_choiceinput_0bc']"
self.context['value'] = {} self.context['value'] = {}
...@@ -842,7 +826,7 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase): ...@@ -842,7 +826,7 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase):
"""Test conditions under which the entire problem """Test conditions under which the entire problem
(not a particular option) is marked correct""" (not a particular option) is marked correct"""
self.context['status'] = 'correct' self.context['status'] = Status('correct')
self.context['input_type'] = 'checkbox' self.context['input_type'] = 'checkbox'
self.context['value'] = self.VALUE_DICT self.context['value'] = self.VALUE_DICT
...@@ -863,14 +847,14 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase): ...@@ -863,14 +847,14 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase):
(not a particular option) is marked incorrect""" (not a particular option) is marked incorrect"""
grouping_tags = {'radio': 'label', 'checkbox': 'section'} grouping_tags = {'radio': 'label', 'checkbox': 'section'}
conditions = [ conditions = [
{'status': 'incorrect', 'status_class': 'incorrect', 'input_type': 'radio', 'value': {}}, {'status': Status('incorrect'), 'input_type': 'radio', 'value': {}},
{'status': 'incorrect', 'status_class': 'incorrect', 'input_type': 'checkbox', 'value': self.WRONG_CHOICE_CHECKBOX}, {'status': Status('incorrect'), 'input_type': 'checkbox', 'value': self.WRONG_CHOICE_CHECKBOX},
{'status': 'incorrect', 'status_class': 'incorrect', 'input_type': 'checkbox', 'value': self.BOTH_CHOICE_CHECKBOX}, {'status': Status('incorrect'), 'input_type': 'checkbox', 'value': self.BOTH_CHOICE_CHECKBOX},
{'status': 'incorrect', 'status_class': 'incorrect', 'input_type': 'checkbox', 'value': self.VALUE_DICT}, {'status': Status('incorrect'), 'input_type': 'checkbox', 'value': self.VALUE_DICT},
{'status': 'incomplete', 'status_class': 'incorrect', 'input_type': 'radio', 'value': {}}, {'status': Status('incomplete'), 'input_type': 'radio', 'value': {}},
{'status': 'incomplete', 'status_class': 'incorrect', 'input_type': 'checkbox', 'value': self.WRONG_CHOICE_CHECKBOX}, {'status': Status('incomplete'), 'input_type': 'checkbox', 'value': self.WRONG_CHOICE_CHECKBOX},
{'status': 'incomplete', 'status_class': 'incorrect', 'input_type': 'checkbox', 'value': self.BOTH_CHOICE_CHECKBOX}, {'status': Status('incomplete'), 'input_type': 'checkbox', 'value': self.BOTH_CHOICE_CHECKBOX},
{'status': 'incomplete', 'status_class': 'incorrect', 'input_type': 'checkbox', 'value': self.VALUE_DICT}] {'status': Status('incomplete'), 'input_type': 'checkbox', 'value': self.VALUE_DICT}]
for test_conditions in conditions: for test_conditions in conditions:
self.context.update(test_conditions) self.context.update(test_conditions)
...@@ -894,15 +878,14 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase): ...@@ -894,15 +878,14 @@ class ChoiceTextGroupTemplateTest(TemplateTestCase):
grouping_tags = {'radio': 'label', 'checkbox': 'section'} grouping_tags = {'radio': 'label', 'checkbox': 'section'}
conditions = [ conditions = [
{'status': 'unsubmitted', 'input_type': 'radio', 'value': {}}, {'status': Status('unsubmitted'), 'input_type': 'radio', 'value': {}},
{'status': 'unsubmitted', 'input_type': 'radio', 'value': self.EMPTY_DICT}, {'status': Status('unsubmitted'), 'input_type': 'radio', 'value': self.EMPTY_DICT},
{'status': 'unsubmitted', 'input_type': 'checkbox', 'value': {}}, {'status': Status('unsubmitted'), 'input_type': 'checkbox', 'value': {}},
{'status': 'unsubmitted', 'input_type': 'checkbox', 'value': self.EMPTY_DICT}, {'status': Status('unsubmitted'), 'input_type': 'checkbox', 'value': self.EMPTY_DICT},
{'status': 'unsubmitted', 'input_type': 'checkbox', 'value': self.VALUE_DICT}, {'status': Status('unsubmitted'), 'input_type': 'checkbox', 'value': self.VALUE_DICT},
{'status': 'unsubmitted', 'input_type': 'checkbox', 'value': self.BOTH_CHOICE_CHECKBOX}] {'status': Status('unsubmitted'), 'input_type': 'checkbox', 'value': self.BOTH_CHOICE_CHECKBOX}]
self.context['status'] = 'unanswered' self.context['status'] = Status('unanswered')
self.context['status_class'] = 'unanswered'
for test_conditions in conditions: for test_conditions in conditions:
self.context.update(test_conditions) self.context.update(test_conditions)
......
...@@ -58,9 +58,7 @@ class OptionInputTest(unittest.TestCase): ...@@ -58,9 +58,7 @@ class OptionInputTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'value': 'Down', 'value': 'Down',
'options': [('Up', 'Up'), ('Down', 'Down'), ('Don\'t know', 'Don\'t know')], 'options': [('Up', 'Up'), ('Down', 'Down'), ('Don\'t know', 'Don\'t know')],
'status': 'answered', 'status': inputtypes.Status('answered'),
'status_class': 'answered',
'status_display': 'answered',
'label': '', 'label': '',
'msg': '', 'msg': '',
'inline': False, 'inline': False,
...@@ -120,9 +118,7 @@ class ChoiceGroupTest(unittest.TestCase): ...@@ -120,9 +118,7 @@ class ChoiceGroupTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'sky_input', 'id': 'sky_input',
'value': 'foil3', 'value': 'foil3',
'status': 'answered', 'status': inputtypes.Status('answered'),
'status_class': 'answered',
'status_display': 'answered',
'label': '', 'label': '',
'msg': '', 'msg': '',
'input_type': expected_input_type, 'input_type': expected_input_type,
...@@ -175,9 +171,7 @@ class JavascriptInputTest(unittest.TestCase): ...@@ -175,9 +171,7 @@ class JavascriptInputTest(unittest.TestCase):
expected = { expected = {
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'status': 'unanswered', 'status': inputtypes.Status('unanswered'),
'status_class': 'unanswered',
'status_display': u'unanswered',
# 'label': '', # 'label': '',
'msg': '', 'msg': '',
'value': '3', 'value': '3',
...@@ -210,9 +204,7 @@ class TextLineTest(unittest.TestCase): ...@@ -210,9 +204,7 @@ class TextLineTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': 'BumbleBee', 'value': 'BumbleBee',
'status': 'unanswered', 'status': inputtypes.Status('unanswered'),
'status_class': 'unanswered',
'status_display': u'unanswered',
'label': 'testing 123', 'label': 'testing 123',
'size': size, 'size': size,
'msg': '', 'msg': '',
...@@ -244,9 +236,7 @@ class TextLineTest(unittest.TestCase): ...@@ -244,9 +236,7 @@ class TextLineTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': 'BumbleBee', 'value': 'BumbleBee',
'status': 'unanswered', 'status': inputtypes.Status('unanswered'),
'status_class': 'unanswered',
'status_display': u'unanswered',
'label': '', 'label': '',
'size': size, 'size': size,
'msg': '', 'msg': '',
...@@ -290,9 +280,7 @@ class TextLineTest(unittest.TestCase): ...@@ -290,9 +280,7 @@ class TextLineTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': 'BumbleBee', 'value': 'BumbleBee',
'status': 'unanswered', 'status': inputtypes.Status('unanswered'),
'status_class': 'unanswered',
'status_display': u'unanswered',
'label': '', 'label': '',
'size': size, 'size': size,
'msg': '', 'msg': '',
...@@ -333,9 +321,7 @@ class FileSubmissionTest(unittest.TestCase): ...@@ -333,9 +321,7 @@ class FileSubmissionTest(unittest.TestCase):
expected = { expected = {
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'status': 'queued', 'status': inputtypes.Status('queued'),
'status_class': 'processing',
'status_display': u'queued',
'label': '', 'label': '',
'msg': the_input.submitted_msg, 'msg': the_input.submitted_msg,
'value': 'BumbleBee.py', 'value': 'BumbleBee.py',
...@@ -385,9 +371,7 @@ class CodeInputTest(unittest.TestCase): ...@@ -385,9 +371,7 @@ class CodeInputTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': 'print "good evening"', 'value': 'print "good evening"',
'status': 'queued', 'status': inputtypes.Status('queued'),
'status_class': 'processing',
'status_display': u'queued',
# 'label': '', # 'label': '',
'msg': the_input.submitted_msg, 'msg': the_input.submitted_msg,
'mode': mode, 'mode': mode,
...@@ -441,9 +425,7 @@ class MatlabTest(unittest.TestCase): ...@@ -441,9 +425,7 @@ class MatlabTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': 'print "good evening"', 'value': 'print "good evening"',
'status': 'queued', 'status': inputtypes.Status('queued'),
'status_class': 'processing',
'status_display': u'queued',
# 'label': '', # 'label': '',
'msg': self.the_input.submitted_msg, 'msg': self.the_input.submitted_msg,
'mode': self.mode, 'mode': self.mode,
...@@ -474,9 +456,7 @@ class MatlabTest(unittest.TestCase): ...@@ -474,9 +456,7 @@ class MatlabTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': 'print "good evening"', 'value': 'print "good evening"',
'status': 'queued', 'status': inputtypes.Status('queued'),
'status_class': 'processing',
'status_display': u'queued',
# 'label': '', # 'label': '',
'msg': the_input.submitted_msg, 'msg': the_input.submitted_msg,
'mode': self.mode, 'mode': self.mode,
...@@ -507,9 +487,7 @@ class MatlabTest(unittest.TestCase): ...@@ -507,9 +487,7 @@ class MatlabTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': 'print "good evening"', 'value': 'print "good evening"',
'status': status, 'status': inputtypes.Status(status),
'status_class': status,
'status_display': unicode(status),
# 'label': '', # 'label': '',
'msg': '', 'msg': '',
'mode': self.mode, 'mode': self.mode,
...@@ -540,9 +518,7 @@ class MatlabTest(unittest.TestCase): ...@@ -540,9 +518,7 @@ class MatlabTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': 'print "good evening"', 'value': 'print "good evening"',
'status': 'queued', 'status': inputtypes.Status('queued'),
'status_class': 'processing',
'status_display': u'queued',
# 'label': '', # 'label': '',
'msg': the_input.submitted_msg, 'msg': the_input.submitted_msg,
'mode': self.mode, 'mode': self.mode,
...@@ -657,7 +633,7 @@ class MatlabTest(unittest.TestCase): ...@@ -657,7 +633,7 @@ class MatlabTest(unittest.TestCase):
output = self.the_input.get_html() output = self.the_input.get_html()
self.assertEqual( self.assertEqual(
etree.tostring(output), etree.tostring(output),
"""<div>{\'status\': \'queued\', \'button_enabled\': True, \'linenumbers\': \'true\', \'rows\': \'10\', \'queue_len\': \'3\', \'mode\': \'\', \'cols\': \'80\', \'value\': \'print "good evening"\', \'status_class\': \'processing\', \'queue_msg\': \'\', \'STATIC_URL\': \'/dummy-static/\', \'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\': \'\', \'status_display\': u\'queued\', \'id\': \'prob_1_2\', \'tabsize\': 4}</div>""" """<div>{\'status\': Status(\'queued\'), \'button_enabled\': True, \'rows\': \'10\', \'queue_len\': \'3\', \'mode\': \'\', \'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\': \'\', \'id\': \'prob_1_2\', \'tabsize\': 4}</div>"""
) )
# test html, that is correct HTML5 html, but is not parsable by XML parser. # test html, that is correct HTML5 html, but is not parsable by XML parser.
...@@ -775,9 +751,7 @@ class SchematicTest(unittest.TestCase): ...@@ -775,9 +751,7 @@ class SchematicTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': value, 'value': value,
'status': 'unsubmitted', 'status': inputtypes.Status('unsubmitted'),
'status_class': 'unanswered',
'status_display': u'unanswered',
'label': '', 'label': '',
'msg': '', 'msg': '',
'initial_value': initial_value, 'initial_value': initial_value,
...@@ -821,9 +795,7 @@ class ImageInputTest(unittest.TestCase): ...@@ -821,9 +795,7 @@ class ImageInputTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': value, 'value': value,
'status': 'unsubmitted', 'status': inputtypes.Status('unsubmitted'),
'status_class': 'unanswered',
'status_display': u'unanswered',
'label': '', 'label': '',
'width': width, 'width': width,
'height': height, 'height': height,
...@@ -878,9 +850,7 @@ class CrystallographyTest(unittest.TestCase): ...@@ -878,9 +850,7 @@ class CrystallographyTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': value, 'value': value,
'status': 'unsubmitted', 'status': inputtypes.Status('unsubmitted'),
'status_class': 'unanswered',
'status_display': u'unanswered',
# 'label': '', # 'label': '',
'msg': '', 'msg': '',
'width': width, 'width': width,
...@@ -922,9 +892,7 @@ class VseprTest(unittest.TestCase): ...@@ -922,9 +892,7 @@ class VseprTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': value, 'value': value,
'status': 'unsubmitted', 'status': inputtypes.Status('unsubmitted'),
'status_class': 'unanswered',
'status_display': u'unanswered',
'msg': '', 'msg': '',
'width': width, 'width': width,
'height': height, 'height': height,
...@@ -956,9 +924,7 @@ class ChemicalEquationTest(unittest.TestCase): ...@@ -956,9 +924,7 @@ class ChemicalEquationTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': 'H2OYeah', 'value': 'H2OYeah',
'status': 'unanswered', 'status': inputtypes.Status('unanswered'),
'status_class': 'unanswered',
'status_display': 'unanswered',
'label': '', 'label': '',
'msg': '', 'msg': '',
'size': self.size, 'size': self.size,
...@@ -1046,9 +1012,7 @@ class FormulaEquationTest(unittest.TestCase): ...@@ -1046,9 +1012,7 @@ class FormulaEquationTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': 'x^2+1/2', 'value': 'x^2+1/2',
'status': 'unanswered', 'status': inputtypes.Status('unanswered'),
'status_class': 'unanswered',
'status_display': u'unanswered',
'label': '', 'label': '',
'msg': '', 'msg': '',
'size': self.size, 'size': self.size,
...@@ -1155,14 +1119,14 @@ class DragAndDropTest(unittest.TestCase): ...@@ -1155,14 +1119,14 @@ class DragAndDropTest(unittest.TestCase):
"target_outline": "false", "target_outline": "false",
"base_image": "/dummy-static/images/about_1.png", "base_image": "/dummy-static/images/about_1.png",
"draggables": [ "draggables": [
{"can_reuse": "", "label": "Label 1", "id": "1", "icon": "", "target_fields": []}, {"can_reuse": "", "label": "Label 1", "id": "1", "icon": "", "target_fields": []},
{"can_reuse": "", "label": "cc", "id": "name_with_icon", "icon": "/dummy-static/images/cc.jpg", "target_fields": []}, {"can_reuse": "", "label": "cc", "id": "name_with_icon", "icon": "/dummy-static/images/cc.jpg", "target_fields": []},
{"can_reuse": "", "label": "arrow-left", "id": "with_icon", "icon": "/dummy-static/images/arrow-left.png", "can_reuse": "", "target_fields": []}, {"can_reuse": "", "label": "arrow-left", "id": "with_icon", "icon": "/dummy-static/images/arrow-left.png", "target_fields": []},
{"can_reuse": "", "label": "Label2", "id": "5", "icon": "", "can_reuse": "", "target_fields": []}, {"can_reuse": "", "label": "Label2", "id": "5", "icon": "", "target_fields": []},
{"can_reuse": "", "label": "Mute", "id": "2", "icon": "/dummy-static/images/mute.png", "can_reuse": "", "target_fields": []}, {"can_reuse": "", "label": "Mute", "id": "2", "icon": "/dummy-static/images/mute.png", "target_fields": []},
{"can_reuse": "", "label": "spinner", "id": "name_label_icon3", "icon": "/dummy-static/images/spinner.gif", "can_reuse": "", "target_fields": []}, {"can_reuse": "", "label": "spinner", "id": "name_label_icon3", "icon": "/dummy-static/images/spinner.gif", "target_fields": []},
{"can_reuse": "", "label": "Star", "id": "name4", "icon": "/dummy-static/images/volume.png", "can_reuse": "", "target_fields": []}, {"can_reuse": "", "label": "Star", "id": "name4", "icon": "/dummy-static/images/volume.png", "target_fields": []},
{"can_reuse": "", "label": "Label3", "id": "7", "icon": "", "can_reuse": "", "target_fields": []}], {"can_reuse": "", "label": "Label3", "id": "7", "icon": "", "target_fields": []}],
"one_per_target": "True", "one_per_target": "True",
"targets": [ "targets": [
{"y": "90", "x": "210", "id": "t1", "w": "90", "h": "90"}, {"y": "90", "x": "210", "id": "t1", "w": "90", "h": "90"},
...@@ -1177,9 +1141,7 @@ class DragAndDropTest(unittest.TestCase): ...@@ -1177,9 +1141,7 @@ class DragAndDropTest(unittest.TestCase):
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'prob_1_2', 'id': 'prob_1_2',
'value': value, 'value': value,
'status': 'unsubmitted', 'status': inputtypes.Status('unsubmitted'),
'status_class': 'unanswered',
'status_display': u'unanswered',
# 'label': '', # 'label': '',
'msg': '', 'msg': '',
'drag_and_drop_json': json.dumps(user_input) 'drag_and_drop_json': json.dumps(user_input)
...@@ -1231,10 +1193,7 @@ class AnnotationInputTest(unittest.TestCase): ...@@ -1231,10 +1193,7 @@ class AnnotationInputTest(unittest.TestCase):
expected = { expected = {
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
'id': 'annotation_input', 'id': 'annotation_input',
'value': value, 'status': inputtypes.Status('answered'),
'status': 'answered',
'status_class': 'answered',
'status_display': 'answered',
# 'label': '', # 'label': '',
'msg': '', 'msg': '',
'title': 'foo', 'title': 'foo',
...@@ -1294,9 +1253,7 @@ class TestChoiceText(unittest.TestCase): ...@@ -1294,9 +1253,7 @@ class TestChoiceText(unittest.TestCase):
state = { state = {
'value': '{}', 'value': '{}',
'id': 'choicetext_input', 'id': 'choicetext_input',
'status': 'answered', 'status': inputtypes.Status('answered'),
'status_class': 'answered',
'status_display': u'answered',
} }
first_input = self.build_choice_element('numtolerance_input', 'choiceinput_0_textinput_0', 'false', '') first_input = self.build_choice_element('numtolerance_input', 'choiceinput_0_textinput_0', 'false', '')
...@@ -1352,3 +1309,63 @@ class TestChoiceText(unittest.TestCase): ...@@ -1352,3 +1309,63 @@ class TestChoiceText(unittest.TestCase):
""" """
with self.assertRaisesRegexp(Exception, "Error in xml"): with self.assertRaisesRegexp(Exception, "Error in xml"):
self.check_group('checkboxtextgroup', 'invalid', 'checkbox') self.check_group('checkboxtextgroup', 'invalid', 'checkbox')
class TestStatus(unittest.TestCase):
"""
Tests for Status class
"""
def test_str(self):
"""
Test stringifing Status objects
"""
statobj = inputtypes.Status('test')
self.assertEqual(str(statobj), 'test')
self.assertEqual(unicode(statobj), u'test')
def test_classes(self):
"""
Test that css classnames are correct
"""
css_classes = [
('unsubmitted', 'unanswered'),
('incomplete', 'incorrect'),
('queued', 'processing'),
('correct', 'correct'),
('test', 'test'),
]
for status, classname in css_classes:
statobj = inputtypes.Status(status)
self.assertEqual(statobj.classname, classname)
def test_display_names(self):
"""
Test that display names are correct
"""
names = [
('correct', u'correct'),
('incorrect', u'incorrect'),
('incomplete', u'incomplete'),
('unanswered', u'unanswered'),
('unsubmitted', u'unanswered'),
('queued', u'processing'),
('dave', u'dave'),
]
for status, display_name in names:
statobj = inputtypes.Status(status)
self.assertEqual(statobj.display_name, display_name)
def test_translated_names(self):
"""
Test that display names are "translated"
"""
func = lambda t: t.upper()
# status is in the mapping
statobj = inputtypes.Status('queued', func)
self.assertEqual(statobj.display_name, u'PROCESSING')
# status is not in the mapping
statobj = inputtypes.Status('test', func)
self.assertEqual(statobj.display_name, u'test')
self.assertEqual(str(statobj), 'test')
self.assertEqual(statobj.classname, 'test')
...@@ -4,6 +4,7 @@ class @HTMLModule ...@@ -4,6 +4,7 @@ class @HTMLModule
@el = $(@element) @el = $(@element)
JavascriptLoader.executeModuleScripts(@el) JavascriptLoader.executeModuleScripts(@el)
Collapsible.setCollapsibles(@el) Collapsible.setCollapsibles(@el)
if MathJax?
MathJax.Hub.Queue ["Typeset", MathJax.Hub, @el[0]] MathJax.Hub.Queue ["Typeset", MathJax.Hub, @el[0]]
$: (selector) -> $: (selector) ->
......
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