diff --git a/freetextresponse/__init__.py b/freetextresponse/__init__.py index b21bc078..e0e947c1 100644 --- a/freetextresponse/__init__.py +++ b/freetextresponse/__init__.py @@ -4,4 +4,4 @@ present in order for the student to receive credit. """ -__version__ = "3.2.0" +__version__ = "3.2.1" diff --git a/freetextresponse/tests/submitdisplay_class.json b/freetextresponse/tests/submitdisplay_class.json index 621d38e9..86b7d888 100644 --- a/freetextresponse/tests/submitdisplay_class.json +++ b/freetextresponse/tests/submitdisplay_class.json @@ -1,7 +1,12 @@ { + "empty_null_max": { + "max_attempts": null, + "count_attempts": 1, + "result": "" + }, "empty_zero_max": { "max_attempts": 0, - "count_attempts": 1, + "count_attempts": 1, "result": "" }, "empty_under_max": { diff --git a/freetextresponse/tests/test_all.py b/freetextresponse/tests/test_all.py index 39d8aca4..4d972367 100644 --- a/freetextresponse/tests/test_all.py +++ b/freetextresponse/tests/test_all.py @@ -1,6 +1,7 @@ """ Module To Test FreeTextResponse XBlock """ +from datetime import datetime, timedelta from os import path import json import unittest @@ -88,7 +89,7 @@ def test_generate_validation_message(self): def test_validate_field_data(self, **test_dict): """ Checks classmethod validate_field_data - tests the instuctor values set in edit + tests the instructor values set in edit """ test_data = TestData() test_data.weight = test_dict['weight'] @@ -324,6 +325,7 @@ def test_word_count_valid(self, **test_data): # Messages @ddt.data( # max_attempts, count_attempts, result + (None, 4, ''), (0, 4, ''), (1, 0, 'You have used 0 of 1 submission'), (3, 2, 'You have used 2 of 3 submissions'), @@ -412,7 +414,7 @@ def test_get_submitted_message( Tests _get_submitted_message Returns a message to display to the user after they submit a - resopnse + response """ self.xblock._word_count_valid = MagicMock( return_value=word_count_valid @@ -497,12 +499,53 @@ def test_get_submitdisplay_class(self, **test_data): self.xblock._get_nodisplay_class() ) - def test_submit(self): + @ddt.data( + ({'max_attempts': None, 'count_attempts': 1}, True), + ({'max_attempts': None, 'count_attempts': 3}, True), + ({'max_attempts': 0, 'count_attempts': 3}, True), + ({'max_attempts': 3, 'count_attempts': 2}, True), + ({'max_attempts': 3, 'count_attempts': 3}, False), + ({'due': None, 'graceperiod': None}, True), + ({'due': None, 'graceperiod': timedelta(hours=1)}, True), + ( + { + 'due': datetime.utcnow() + timedelta(hours=1), + 'graceperiod': None, + }, + True, + ), + ( + { + 'due': datetime.utcnow() - timedelta(hours=1), + 'graceperiod': None, + }, + False, + ), + ( + { + 'due': datetime.utcnow() - timedelta(hours=1), + 'graceperiod': timedelta(hours=2), + }, + True, + ), + ( + { + 'due': datetime.utcnow() - timedelta(hours=5), + 'graceperiod': timedelta(hours=2), + }, + False, + ), + ) + @ddt.unpack + def test_submit(self, xblock_config, can_submit): # pylint: disable=protected-access """ - Tests save_reponse results + Tests save_response results """ - data = json.dumps({'student_answer': 'asdf'}) + student_answer = 'asdf' + for key, value in xblock_config.items(): + setattr(self.xblock, key, value) + data = json.dumps({'student_answer': student_answer}) request = TestRequest() request.method = 'POST' request.body = data.encode('utf-8') @@ -543,13 +586,27 @@ def test_submit(self): response.json_body['visibility_class'], self.xblock._get_indicator_visibility_class() ) + self.assertEqual( + self.xblock.student_answer, + student_answer if can_submit else '' + ) - def test_save_reponse(self): + @ddt.data( + ({'max_attempts': None, 'count_attempts': 1}, True), + ({'max_attempts': None, 'count_attempts': 3}, True), + ({'max_attempts': 0, 'count_attempts': 3}, True), + ({'max_attempts': 3, 'count_attempts': 3}, False) + ) + @ddt.unpack + def test_save_response(self, xblock_config, can_save): # pylint: disable=protected-access """ - Tests save_reponse results + Tests save_response results """ - data = json.dumps({'student_answer': 'asdf'}) + student_answer = 'asdf' + for key, value in xblock_config.items(): + setattr(self.xblock, key, value) + data = json.dumps({'student_answer': student_answer}) request = TestRequest() request.method = 'POST' request.body = data.encode('utf-8') @@ -587,3 +644,7 @@ def test_save_reponse(self): response.json_body['visibility_class'], self.xblock._get_indicator_visibility_class() ) + self.assertEqual( + self.xblock.student_answer, + student_answer if can_save else '' + ) diff --git a/freetextresponse/tests/validate_field_data.json b/freetextresponse/tests/validate_field_data.json index 3510c75c..d99c8c81 100644 --- a/freetextresponse/tests/validate_field_data.json +++ b/freetextresponse/tests/validate_field_data.json @@ -1,5 +1,5 @@ { - "weight_attemps_negative": { + "weight_attempts_negative": { "weight": -1, "max_attempts": 1, "max_word_count": 1, @@ -7,7 +7,7 @@ "submitted_message": "s", "result": "Weight Attempts cannot be negative" }, - "max_attemps_negative": { + "max_attempts_negative": { "weight": 0, "max_attempts": -1, "max_word_count": 1, diff --git a/freetextresponse/views.py b/freetextresponse/views.py index fa6e4ab9..55b5df47 100644 --- a/freetextresponse/views.py +++ b/freetextresponse/views.py @@ -74,7 +74,7 @@ def _get_nodisplay_class(self): Returns the css class for the submit button """ result = '' - if self.max_attempts > 0 and self.count_attempts >= self.max_attempts: + if self.max_attempts and 0 < self.max_attempts <= self.count_attempts: result = 'nodisplay' return result @@ -142,7 +142,7 @@ def _get_used_attempts_feedback(self): they have used if applicable """ result = '' - if self.max_attempts > 0: + if self.max_attempts and self.max_attempts > 0: result = self.ngettext( 'You have used {count_attempts} of {max_attempts} submission', 'You have used {count_attempts} of {max_attempts} submissions', @@ -206,7 +206,7 @@ def submit(self, data, suffix=''): Processes the user's submission """ # Fails if the UI submit/save buttons were shut - # down on the previous sumbisson + # down on the previous submission if self._can_submit(): self.student_answer = data['student_answer'] # Counting the attempts and publishing a score @@ -239,8 +239,8 @@ def save_reponse(self, data, suffix=''): Processes the user's save """ # Fails if the UI submit/save buttons were shut - # down on the previous sumbisson - if self.max_attempts == 0 or self.count_attempts < self.max_attempts: + # down on the previous submission + if not self.max_attempts or self.count_attempts < self.max_attempts: self.student_answer = data['student_answer'] result = { 'status': 'success', @@ -295,7 +295,7 @@ def _can_submit(self): """ if self.is_past_due(): return False - if self.max_attempts == 0: + if not self.max_attempts: return True if self.count_attempts < self.max_attempts: return True