Commit 0c4d6ba6 by Felix Sun

Made explanation for hints field in crowdsource_hinter.py more clear.

Fixed various commenting things.

Removed an unused function in the crowdsourced module coffeescript.

Improved commenting in hint_manager.

Fixed pep and pylint violations.
parent 0b25e761
...@@ -29,13 +29,16 @@ class CrowdsourceHinterFields(object): ...@@ -29,13 +29,16 @@ class CrowdsourceHinterFields(object):
default='False') default='False')
debug = String(help='String "True"/"False" - allows multiple voting', scope=Scope.content, debug = String(help='String "True"/"False" - allows multiple voting', scope=Scope.content,
default='False') default='False')
# hints[answer] = {str(pk): [hint_text, #votes]} # Usage: hints[answer] = {str(pk): [hint_text, #votes]}
# hints is a dictionary that takes answer keys.
# Each value is itself a dictionary, accepting hint_pk strings as keys,
# and returning [hint text, #votes] pairs as values
hints = Dict(help='A dictionary containing all the active hints.', scope=Scope.content, default={}) hints = Dict(help='A dictionary containing all the active hints.', scope=Scope.content, default={})
mod_queue = Dict(help='A dictionary containing hints still awaiting approval', scope=Scope.content, mod_queue = Dict(help='A dictionary containing hints still awaiting approval', scope=Scope.content,
default={}) default={})
hint_pk = Integer(help='Used to index hints.', scope=Scope.content, default=0) hint_pk = Integer(help='Used to index hints.', scope=Scope.content, default=0)
# A list of previous answers this student made to this problem. # A list of previous answers this student made to this problem.
# Of the form (answer, (hint_pk_1, hint_pk_2, hint_pk_3)) for each problem. hint_pk's are # Of the form [answer, [hint_pk_1, hint_pk_2, hint_pk_3]] for each problem. hint_pk's are
# None if the hint was not given. # None if the hint was not given.
previous_answers = List(help='A list of previous submissions.', scope=Scope.user_state, default=[]) previous_answers = List(help='A list of previous submissions.', scope=Scope.user_state, default=[])
user_voted = Boolean(help='Specifies if the user has voted on this problem or not.', user_voted = Boolean(help='Specifies if the user has voted on this problem or not.',
...@@ -166,7 +169,7 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule): ...@@ -166,7 +169,7 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule):
random.sample(local_hints[answer].items(), 2) random.sample(local_hints[answer].items(), 2)
rand_hint_1 = rand_hint_1[0] rand_hint_1 = rand_hint_1[0]
rand_hint_2 = rand_hint_2[0] rand_hint_2 = rand_hint_2[0]
self.previous_answers += [(answer, (best_hint_index, hint_index_1, hint_index_2))] self.previous_answers += [[answer, [best_hint_index, hint_index_1, hint_index_2]]]
return {'best_hint': best_hint, return {'best_hint': best_hint,
'rand_hint_1': rand_hint_1, 'rand_hint_1': rand_hint_1,
...@@ -185,7 +188,6 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule): ...@@ -185,7 +188,6 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule):
""" """
# The student got it right. # The student got it right.
# Did he submit at least one wrong answer? # Did he submit at least one wrong answer?
out = ''
if len(self.previous_answers) == 0: if len(self.previous_answers) == 0:
# No. Nothing to do here. # No. Nothing to do here.
return return
......
...@@ -61,13 +61,6 @@ class @Hinter ...@@ -61,13 +61,6 @@ class @Hinter
target.val('') target.val('')
target.data('cleared', true) target.data('cleared', true)
feedback_ui_change: =>
# Make all of the previous-answer divs hidden.
@$('.previous-answer').css('display', 'none')
# But, now find the selected div, and make it visible.
selector = '#previous-answer-' + @$('#feedback-select option:selected').attr('value')
@$(selector).css('display', 'inline')
render: (content) -> render: (content) ->
if content if content
# Trim leading and trailing whitespace # Trim leading and trailing whitespace
......
from mock import Mock, patch """
Tests the crowdsourced hinter xmodule.
"""
from mock import Mock
import unittest import unittest
import copy import copy
import random
import xmodule
from xmodule.crowdsource_hinter import CrowdsourceHinterModule from xmodule.crowdsource_hinter import CrowdsourceHinterModule
from xmodule.vertical_module import VerticalModule, VerticalDescriptor from xmodule.vertical_module import VerticalModule, VerticalDescriptor
from xmodule.modulestore import Location
from django.http import QueryDict
from . import get_test_system from . import get_test_system
import json import json
class CHModuleFactory(object): class CHModuleFactory(object):
""" """
Helps us make a CrowdsourceHinterModule with the specified internal Helps us make a CrowdsourceHinterModule with the specified internal
...@@ -44,6 +44,9 @@ class CHModuleFactory(object): ...@@ -44,6 +44,9 @@ class CHModuleFactory(object):
@staticmethod @staticmethod
def next_num(): def next_num():
"""
Helps make unique names for our mock CrowdsourceHinterModule's
"""
CHModuleFactory.num += 1 CHModuleFactory.num += 1
return CHModuleFactory.num return CHModuleFactory.num
...@@ -53,23 +56,23 @@ class CHModuleFactory(object): ...@@ -53,23 +56,23 @@ class CHModuleFactory(object):
user_voted=None, user_voted=None,
moderate=None, moderate=None,
mod_queue=None): mod_queue=None):
"""
location = Location(["i4x", "edX", "capa_test", "problem", A factory method for making CHM's
"SampleProblem{0}".format(CHModuleFactory.next_num())]) """
model_data = {'data': CHModuleFactory.sample_problem_xml} model_data = {'data': CHModuleFactory.sample_problem_xml}
if hints != None: if hints is not None:
model_data['hints'] = hints model_data['hints'] = hints
else: else:
model_data['hints'] = { model_data['hints'] = {
'24.0': {'0': ['Best hint', 40], '24.0': {'0': ['Best hint', 40],
'3': ['Another hint', 30], '3': ['Another hint', 30],
'4': ['A third hint', 20], '4': ['A third hint', 20],
'6': ['A less popular hint', 3]}, '6': ['A less popular hint', 3]},
'25.0': {'1': ['Really popular hint', 100]} '25.0': {'1': ['Really popular hint', 100]}
} }
if mod_queue != None: if mod_queue is not None:
model_data['mod_queue'] = mod_queue model_data['mod_queue'] = mod_queue
else: else:
model_data['mod_queue'] = { model_data['mod_queue'] = {
...@@ -77,7 +80,7 @@ class CHModuleFactory(object): ...@@ -77,7 +80,7 @@ class CHModuleFactory(object):
'26.0': {'5': ['Another non-approved hint']} '26.0': {'5': ['Another non-approved hint']}
} }
if previous_answers != None: if previous_answers is not None:
model_data['previous_answers'] = previous_answers model_data['previous_answers'] = previous_answers
else: else:
model_data['previous_answers'] = [ model_data['previous_answers'] = [
...@@ -85,18 +88,19 @@ class CHModuleFactory(object): ...@@ -85,18 +88,19 @@ class CHModuleFactory(object):
['29.0', [None, None, None]] ['29.0', [None, None, None]]
] ]
if user_voted != None: if user_voted is not None:
model_data['user_voted'] = user_voted model_data['user_voted'] = user_voted
if moderate != None: if moderate is not None:
model_data['moderate'] = moderate model_data['moderate'] = moderate
descriptor = Mock(weight="1") descriptor = Mock(weight="1")
system = get_test_system() system = get_test_system()
module = CrowdsourceHinterModule(system, descriptor, model_data) module = CrowdsourceHinterModule(system, descriptor, model_data)
return module return module
class VerticalWithModulesFactory(object): class VerticalWithModulesFactory(object):
""" """
Makes a vertical with several crowdsourced hinter modules inside. Makes a vertical with several crowdsourced hinter modules inside.
...@@ -147,8 +151,6 @@ class VerticalWithModulesFactory(object): ...@@ -147,8 +151,6 @@ class VerticalWithModulesFactory(object):
@staticmethod @staticmethod
def create(): def create():
location = Location(["i4x", "edX", "capa_test", "vertical",
"SampleVertical{0}".format(CHModuleFactory.next_num())])
model_data = {'data': VerticalWithModulesFactory.sample_problem_xml} model_data = {'data': VerticalWithModulesFactory.sample_problem_xml}
system = get_test_system() system = get_test_system()
descriptor = VerticalDescriptor.from_xml(VerticalWithModulesFactory.sample_problem_xml, system) descriptor = VerticalDescriptor.from_xml(VerticalWithModulesFactory.sample_problem_xml, system)
...@@ -166,10 +168,12 @@ class FakeChild(object): ...@@ -166,10 +168,12 @@ class FakeChild(object):
self.system.ajax_url = 'this/is/a/fake/ajax/url' self.system.ajax_url = 'this/is/a/fake/ajax/url'
def get_html(self): def get_html(self):
"""
Return a fake html string.
"""
return 'This is supposed to be test html.' return 'This is supposed to be test html.'
class CrowdsourceHinterTest(unittest.TestCase): class CrowdsourceHinterTest(unittest.TestCase):
""" """
In the below tests, '24.0' represents a wrong answer, and '42.5' represents In the below tests, '24.0' represents a wrong answer, and '42.5' represents
...@@ -178,10 +182,11 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -178,10 +182,11 @@ class CrowdsourceHinterTest(unittest.TestCase):
def test_gethtml(self): def test_gethtml(self):
""" """
A simple test of get_html - make sure it returns the html of the inner A simple test of get_html - make sure it returns the html of the inner
problem. problem.
""" """
m = CHModuleFactory.create() m = CHModuleFactory.create()
def fake_get_display_items(): def fake_get_display_items():
""" """
A mock of get_display_items A mock of get_display_items
...@@ -198,6 +203,7 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -198,6 +203,7 @@ class CrowdsourceHinterTest(unittest.TestCase):
error message. error message.
""" """
m = CHModuleFactory.create() m = CHModuleFactory.create()
def fake_get_display_items(): def fake_get_display_items():
""" """
Returns no children. Returns no children.
...@@ -207,13 +213,13 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -207,13 +213,13 @@ class CrowdsourceHinterTest(unittest.TestCase):
out_html = m.get_html() out_html = m.get_html()
self.assertTrue('Error in loading crowdsourced hinter' in out_html) self.assertTrue('Error in loading crowdsourced hinter' in out_html)
@unittest.skip("Needs to be finished.")
def test_gethtml_multiple(self): def test_gethtml_multiple(self):
""" """
Makes sure that multiple crowdsourced hinters play nice, when get_html Makes sure that multiple crowdsourced hinters play nice, when get_html
is called. is called.
NOT WORKING RIGHT NOW NOT WORKING RIGHT NOW
""" """
return
m = VerticalWithModulesFactory.create() m = VerticalWithModulesFactory.create()
out_html = m.get_html() out_html = m.get_html()
print out_html print out_html
...@@ -229,7 +235,7 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -229,7 +235,7 @@ class CrowdsourceHinterTest(unittest.TestCase):
m = CHModuleFactory.create() m = CHModuleFactory.create()
json_in = {'problem_name': '26.0'} json_in = {'problem_name': '26.0'}
out = m.get_hint(json_in) out = m.get_hint(json_in)
self.assertTrue(out == None) self.assertTrue(out is None)
self.assertTrue(['26.0', [None, None, None]] in m.previous_answers) self.assertTrue(['26.0', [None, None, None]] in m.previous_answers)
def test_gethint_1hint(self): def test_gethint_1hint(self):
...@@ -242,7 +248,6 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -242,7 +248,6 @@ class CrowdsourceHinterTest(unittest.TestCase):
out = m.get_hint(json_in) out = m.get_hint(json_in)
self.assertTrue(out['best_hint'] == 'Really popular hint') self.assertTrue(out['best_hint'] == 'Really popular hint')
def test_gethint_manyhints(self): def test_gethint_manyhints(self):
""" """
Someone asks for a hint, with many matching hints in the database. Someone asks for a hint, with many matching hints in the database.
...@@ -258,7 +263,6 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -258,7 +263,6 @@ class CrowdsourceHinterTest(unittest.TestCase):
self.assertTrue('rand_hint_1' in out) self.assertTrue('rand_hint_1' in out)
self.assertTrue('rand_hint_2' in out) self.assertTrue('rand_hint_2' in out)
def test_getfeedback_0wronganswers(self): def test_getfeedback_0wronganswers(self):
""" """
Someone has gotten the problem correct on the first try. Someone has gotten the problem correct on the first try.
...@@ -267,7 +271,7 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -267,7 +271,7 @@ class CrowdsourceHinterTest(unittest.TestCase):
m = CHModuleFactory.create(previous_answers=[]) m = CHModuleFactory.create(previous_answers=[])
json_in = {'problem_name': '42.5'} json_in = {'problem_name': '42.5'}
out = m.get_feedback(json_in) out = m.get_feedback(json_in)
self.assertTrue(out == None) self.assertTrue(out is None)
def test_getfeedback_1wronganswer_nohints(self): def test_getfeedback_1wronganswer_nohints(self):
""" """
...@@ -275,29 +279,24 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -275,29 +279,24 @@ class CrowdsourceHinterTest(unittest.TestCase):
answer. However, we don't actually have hints for this problem. answer. However, we don't actually have hints for this problem.
There should be a dialog to submit a new hint. There should be a dialog to submit a new hint.
""" """
m = CHModuleFactory.create(previous_answers=[['26.0',[None, None, None]]]) m = CHModuleFactory.create(previous_answers=[['26.0', [None, None, None]]])
json_in = {'problem_name': '42.5'} json_in = {'problem_name': '42.5'}
out = m.get_feedback(json_in) out = m.get_feedback(json_in)
print out['index_to_answer'] print out['index_to_answer']
self.assertTrue(out['index_to_hints'][0] == []) self.assertTrue(out['index_to_hints'][0] == [])
self.assertTrue(out['index_to_answer'][0] == '26.0') self.assertTrue(out['index_to_answer'][0] == '26.0')
def test_getfeedback_1wronganswer_withhints(self): def test_getfeedback_1wronganswer_withhints(self):
""" """
Same as above, except the user did see hints. There should be Same as above, except the user did see hints. There should be
a voting dialog, with the correct choices, plus a hint submission a voting dialog, with the correct choices, plus a hint submission
dialog. dialog.
""" """
m = CHModuleFactory.create( m = CHModuleFactory.create(previous_answers=[['24.0', [0, 3, None]]])
previous_answers=[
['24.0', [0, 3, None]]],
)
json_in = {'problem_name': '42.5'} json_in = {'problem_name': '42.5'}
out = m.get_feedback(json_in) out = m.get_feedback(json_in)
print out['index_to_hints'] print out['index_to_hints']
self.assertTrue(len(out['index_to_hints'][0])==2) self.assertTrue(len(out['index_to_hints'][0]) == 2)
def test_getfeedback_missingkey(self): def test_getfeedback_missingkey(self):
""" """
...@@ -308,7 +307,7 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -308,7 +307,7 @@ class CrowdsourceHinterTest(unittest.TestCase):
previous_answers=[['24.0', [0, 100, None]]]) previous_answers=[['24.0', [0, 100, None]]])
json_in = {'problem_name': '42.5'} json_in = {'problem_name': '42.5'}
out = m.get_feedback(json_in) out = m.get_feedback(json_in)
self.assertTrue(len(out['index_to_hints'][0])==1) self.assertTrue(len(out['index_to_hints'][0]) == 1)
def test_vote_nopermission(self): def test_vote_nopermission(self):
""" """
...@@ -318,10 +317,9 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -318,10 +317,9 @@ class CrowdsourceHinterTest(unittest.TestCase):
m = CHModuleFactory.create(user_voted=True) m = CHModuleFactory.create(user_voted=True)
json_in = {'answer': 0, 'hint': 1} json_in = {'answer': 0, 'hint': 1}
old_hints = copy.deepcopy(m.hints) old_hints = copy.deepcopy(m.hints)
json_out = json.loads(m.tally_vote(json_in))['contents'] m.tally_vote(json_in)
self.assertTrue(m.hints == old_hints) self.assertTrue(m.hints == old_hints)
def test_vote_withpermission(self): def test_vote_withpermission(self):
""" """
A user votes for a hint. A user votes for a hint.
...@@ -336,7 +334,6 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -336,7 +334,6 @@ class CrowdsourceHinterTest(unittest.TestCase):
self.assertTrue(['Best hint', 40] in dict_out['hint_and_votes']) self.assertTrue(['Best hint', 40] in dict_out['hint_and_votes'])
self.assertTrue(['Another hint', 31] in dict_out['hint_and_votes']) self.assertTrue(['Another hint', 31] in dict_out['hint_and_votes'])
def test_submithint_nopermission(self): def test_submithint_nopermission(self):
""" """
A user tries to submit a hint, but he has already voted. A user tries to submit a hint, but he has already voted.
...@@ -348,7 +345,6 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -348,7 +345,6 @@ class CrowdsourceHinterTest(unittest.TestCase):
print m.hints print m.hints
self.assertTrue('29.0' not in m.hints) self.assertTrue('29.0' not in m.hints)
def test_submithint_withpermission_new(self): def test_submithint_withpermission_new(self):
""" """
A user submits a hint to an answer for which no hints A user submits a hint to an answer for which no hints
...@@ -359,21 +355,19 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -359,21 +355,19 @@ class CrowdsourceHinterTest(unittest.TestCase):
m.submit_hint(json_in) m.submit_hint(json_in)
self.assertTrue('29.0' in m.hints) self.assertTrue('29.0' in m.hints)
def test_submithint_withpermission_existing(self): def test_submithint_withpermission_existing(self):
""" """
A user submits a hint to an answer that has other hints A user submits a hint to an answer that has other hints
already. already.
""" """
m = CHModuleFactory.create(previous_answers = [['25.0', [1, None, None]]]) m = CHModuleFactory.create(previous_answers=[['25.0', [1, None, None]]])
json_in = {'answer': 0, 'hint': 'This is a new hint.'} json_in = {'answer': 0, 'hint': 'This is a new hint.'}
m.submit_hint(json_in) m.submit_hint(json_in)
# Make a hint request. # Make a hint request.
json_in = {'problem name': '25.0'} json_in = {'problem name': '25.0'}
out = m.get_hint(json_in) out = m.get_hint(json_in)
self.assertTrue((out['best_hint'] == 'This is a new hint.') self.assertTrue((out['best_hint'] == 'This is a new hint.')
or (out['rand_hint_1'] == 'This is a new hint.')) or (out['rand_hint_1'] == 'This is a new hint.'))
def test_submithint_moderate(self): def test_submithint_moderate(self):
""" """
...@@ -397,7 +391,6 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -397,7 +391,6 @@ class CrowdsourceHinterTest(unittest.TestCase):
print m.hints print m.hints
self.assertTrue(m.hints['29.0'][0][0] == u'<script> alert("Trololo"); </script>') self.assertTrue(m.hints['29.0'][0][0] == u'<script> alert("Trololo"); </script>')
def test_template_gethint(self): def test_template_gethint(self):
""" """
Test the templates for get_hint. Test the templates for get_hint.
...@@ -421,12 +414,11 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -421,12 +414,11 @@ class CrowdsourceHinterTest(unittest.TestCase):
self.assertTrue('A random hint' in out) self.assertTrue('A random hint' in out)
self.assertTrue('Another random hint' in out) self.assertTrue('Another random hint' in out)
def test_template_feedback(self): def test_template_feedback(self):
""" """
Test the templates for get_feedback. Test the templates for get_feedback.
NOT FINISHED NOT FINISHED
from lxml import etree from lxml import etree
m = CHModuleFactory.create() m = CHModuleFactory.create()
...@@ -445,11 +437,3 @@ class CrowdsourceHinterTest(unittest.TestCase): ...@@ -445,11 +437,3 @@ class CrowdsourceHinterTest(unittest.TestCase):
""" """
pass pass
...@@ -60,7 +60,7 @@ What would you say to help someone who got this wrong answer? ...@@ -60,7 +60,7 @@ What would you say to help someone who got this wrong answer?
% endfor % endfor
</div> </div>
<p>Read about <a class="expand-goodhint" href="javascript:;">what makes a good hint</a>.</p> <p>Read about <a class="expand-goodhint" href="javascript:void(0);">what makes a good hint</a>.</p>
<div class="goodhint" style="display:none"> <div class="goodhint" style="display:none">
<h4>What makes a good hint?</h4> <h4>What makes a good hint?</h4>
......
...@@ -22,7 +22,7 @@ from xmodule.modulestore.django import modulestore ...@@ -22,7 +22,7 @@ from xmodule.modulestore.django import modulestore
@ensure_csrf_cookie @ensure_csrf_cookie
def hint_manager(request, course_id): def hint_manager(request, course_id):
try: try:
course = get_course_with_access(request.user, course_id, 'staff', depth=None) get_course_with_access(request.user, course_id, 'staff', depth=None)
except Http404: except Http404:
out = 'Sorry, but students are not allowed to access the hint manager!' out = 'Sorry, but students are not allowed to access the hint manager!'
return HttpResponse(out) return HttpResponse(out)
...@@ -74,12 +74,17 @@ def get_hints(request, course_id, field): ...@@ -74,12 +74,17 @@ def get_hints(request, course_id, field):
other_field = 'mod_queue' other_field = 'mod_queue'
field_label = 'Approved Hints' field_label = 'Approved Hints'
other_field_label = 'Hints Awaiting Moderation' other_field_label = 'Hints Awaiting Moderation'
# The course_id is of the form school/number/classname.
# We want to use the course_id to find all matching definition_id's.
# To do this, just take the school/number part - leave off the classname.
chopped_id = '/'.join(course_id.split('/')[:-1]) chopped_id = '/'.join(course_id.split('/')[:-1])
chopped_id = re.escape(chopped_id) chopped_id = re.escape(chopped_id)
all_hints = XModuleContentField.objects.filter(field_name=field, definition_id__regex=chopped_id) all_hints = XModuleContentField.objects.filter(field_name=field, definition_id__regex=chopped_id)
# big_out_dict[problem id] = [[answer, {pk: [hint, votes]}], sorted by answer] # big_out_dict[problem id] = [[answer, {pk: [hint, votes]}], sorted by answer]
# big_out_dict maps a problem id to a list of [answer, hints] pairs, sorted in order of answer.
big_out_dict = {} big_out_dict = {}
# name_dict[problem id] = Display name of problem # id_to name maps a problem id to the name of the problem.
# id_to_name[problem id] = Display name of problem
id_to_name = {} id_to_name = {}
for hints_by_problem in all_hints: for hints_by_problem in all_hints:
...@@ -88,7 +93,6 @@ def get_hints(request, course_id, field): ...@@ -88,7 +93,6 @@ def get_hints(request, course_id, field):
if name is None: if name is None:
continue continue
id_to_name[hints_by_problem.definition_id] = name id_to_name[hints_by_problem.definition_id] = name
# Answer list contains (answer, dict_of_hints) tuples.
def answer_sorter(thing): def answer_sorter(thing):
""" """
...@@ -102,6 +106,7 @@ def get_hints(request, course_id, field): ...@@ -102,6 +106,7 @@ def get_hints(request, course_id, field):
# Put all non-numerical answers first. # Put all non-numerical answers first.
return float('-inf') return float('-inf')
# Answer list contains [answer, dict_of_hints] pairs.
answer_list = sorted(json.loads(hints_by_problem.value).items(), key=answer_sorter) answer_list = sorted(json.loads(hints_by_problem.value).items(), key=answer_sorter)
big_out_dict[hints_by_problem.definition_id] = answer_list big_out_dict[hints_by_problem.definition_id] = answer_list
...@@ -113,6 +118,7 @@ def get_hints(request, course_id, field): ...@@ -113,6 +118,7 @@ def get_hints(request, course_id, field):
'id_to_name': id_to_name} 'id_to_name': id_to_name}
return render_dict return render_dict
def location_to_problem_name(loc): def location_to_problem_name(loc):
""" """
Given the location of a crowdsource_hinter module, try to return the name of the Given the location of a crowdsource_hinter module, try to return the name of the
...@@ -229,4 +235,4 @@ def approve(request, course_id, field): ...@@ -229,4 +235,4 @@ def approve(request, course_id, field):
problem_dict[answer] = {} problem_dict[answer] = {}
problem_dict[answer][pk] = hint_to_move problem_dict[answer][pk] = hint_to_move
problem_in_hints.value = json.dumps(problem_dict) problem_in_hints.value = json.dumps(problem_dict)
problem_in_hints.save() problem_in_hints.save()
\ No newline at end of file
import unittest
import nose.tools
import json import json
from django.http import Http404
from django.test.client import Client, RequestFactory from django.test.client import Client, RequestFactory
from django.test.utils import override_settings from django.test.utils import override_settings
import mitxmako.middleware
from courseware.models import XModuleContentField from courseware.models import XModuleContentField
from courseware.tests.factories import ContentFactory from courseware.tests.factories import ContentFactory
from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE
import instructor.hint_manager as view import instructor.hint_manager as view
from student.tests.factories import UserFactory, AdminFactory from student.tests.factories import UserFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) @override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE)
class HintManagerTest(ModuleStoreTestCase): class HintManagerTest(ModuleStoreTestCase):
...@@ -36,7 +32,7 @@ class HintManagerTest(ModuleStoreTestCase): ...@@ -36,7 +32,7 @@ class HintManagerTest(ModuleStoreTestCase):
value=json.dumps({'1.0': {'1': ['Hint 1', 2], value=json.dumps({'1.0': {'1': ['Hint 1', 2],
'3': ['Hint 3', 12]}, '3': ['Hint 3', 12]},
'2.0': {'4': ['Hint 4', 3]} '2.0': {'4': ['Hint 4', 3]}
})) }))
ContentFactory.create(field_name='mod_queue', ContentFactory.create(field_name='mod_queue',
definition_id=self.problem_id, definition_id=self.problem_id,
value=json.dumps({'2.0': {'2': ['Hint 2', 1]}})) value=json.dumps({'2.0': {'2': ['Hint 2', 1]}}))
...@@ -48,13 +44,12 @@ class HintManagerTest(ModuleStoreTestCase): ...@@ -48,13 +44,12 @@ class HintManagerTest(ModuleStoreTestCase):
# (I can't figure out how to get fake structures into the modulestore.) # (I can't figure out how to get fake structures into the modulestore.)
view.location_to_problem_name = lambda loc: "Test problem" view.location_to_problem_name = lambda loc: "Test problem"
def test_student_block(self): def test_student_block(self):
""" """
Makes sure that students cannot see the hint management view. Makes sure that students cannot see the hint management view.
""" """
c = Client() c = Client()
user = UserFactory.create(username='student', email='student@edx.org', password='test') UserFactory.create(username='student', email='student@edx.org', password='test')
c.login(username='student', password='test') c.login(username='student', password='test')
out = c.get(self.url) out = c.get(self.url)
print out print out
...@@ -70,7 +65,7 @@ class HintManagerTest(ModuleStoreTestCase): ...@@ -70,7 +65,7 @@ class HintManagerTest(ModuleStoreTestCase):
def test_invalid_field_access(self): def test_invalid_field_access(self):
""" """
Makes sure that field names other than 'mod_queue' and 'hints' are Makes sure that field names other than 'mod_queue' and 'hints' are
rejected. rejected.
""" """
out = self.c.post(self.url, {'op': 'delete hints', 'field': 'all your private data'}) out = self.c.post(self.url, {'op': 'delete hints', 'field': 'all your private data'})
...@@ -110,7 +105,7 @@ class HintManagerTest(ModuleStoreTestCase): ...@@ -110,7 +105,7 @@ class HintManagerTest(ModuleStoreTestCase):
'3': ['Hint 3', 12]}), '3': ['Hint 3', 12]}),
('2.0', {'4': ['Hint 4', 3]}) ('2.0', {'4': ['Hint 4', 3]})
]} ]}
self.assertTrue(out['all_hints'] == expected) self.assertTrue(out['all_hints'] == expected)
def test_deletehints(self): def test_deletehints(self):
""" """
...@@ -167,6 +162,3 @@ class HintManagerTest(ModuleStoreTestCase): ...@@ -167,6 +162,3 @@ class HintManagerTest(ModuleStoreTestCase):
problem_hints = XModuleContentField.objects.get(field_name='hints', definition_id=self.problem_id).value problem_hints = XModuleContentField.objects.get(field_name='hints', definition_id=self.problem_id).value
self.assertTrue(json.loads(problem_hints)['2.0']['2'] == ['Hint 2', 1]) self.assertTrue(json.loads(problem_hints)['2.0']['2'] == ['Hint 2', 1])
self.assertTrue(len(json.loads(problem_hints)['2.0']) == 2) self.assertTrue(len(json.loads(problem_hints)['2.0']) == 2)
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