diff --git a/Changelog.md b/Changelog.md index c3ea12ceb..479a42007 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,8 @@ +Version 2.1.4 (2017-11-06) +--------------------------- + +* Make XBlock always emit `progress` event explicitly when it is marked as complete. + Version 2.1.3 (2017-10-05) --------------------------- diff --git a/drag_and_drop_v2_new/drag_and_drop_v2.py b/drag_and_drop_v2_new/drag_and_drop_v2.py index 2a29c672f..1bd4afc20 100644 --- a/drag_and_drop_v2_new/drag_and_drop_v2.py +++ b/drag_and_drop_v2_new/drag_and_drop_v2.py @@ -774,6 +774,9 @@ def _mark_complete_and_publish_grade(self): self.raw_earned = current_raw_earned self._publish_grade(Score(self.raw_earned, self.max_score())) + # and no matter what - emit progress event for current user + self.runtime.publish(self, "progress", {}) + def _publish_item_dropped_event(self, attempt, is_correct): """ Publishes item dropped event. diff --git a/install_test_deps.sh b/install_test_deps.sh old mode 100644 new mode 100755 diff --git a/tests/integration/test_events.py b/tests/integration/test_events.py index 1d462c1b6..4d2494fcf 100644 --- a/tests/integration/test_events.py +++ b/tests/integration/test_events.py @@ -43,6 +43,10 @@ class EventsFiredTest(DefaultDataTestMixin, ParameterizedTestsMixin, BaseEventsT 'name': 'grade', 'data': {'max_value': 1, 'value': (2.0 / 5), 'only_if_higher': None}, }, + { + 'name': 'progress', + 'data': {} + }, { 'name': 'edx.drag_and_drop_v2.item.dropped', 'data': { @@ -123,6 +127,10 @@ class AssessmentEventsFiredTest( 'name': 'grade', 'data': {'max_value': 1, 'value': (1.0 / 5), 'only_if_higher': None}, }, + { + 'name': 'progress', + 'data': {} + }, { 'name': 'edx.drag_and_drop_v2.feedback.opened', 'data': { diff --git a/tests/unit/test_advanced.py b/tests/unit/test_advanced.py index 8ddfad7bc..cb56dea0a 100644 --- a/tests/unit/test_advanced.py +++ b/tests/unit/test_advanced.py @@ -405,14 +405,19 @@ def test_do_attempt_correct_mark_complete_and_publish_grade(self, weight): res = self.call_handler(self.DO_ATTEMPT_HANDLER, data={}) self.assertTrue(self.block.completed) - patched_publish.assert_called_once_with(self.block, 'grade', { - 'value': 1, - 'max_value': 1, - 'only_if_higher': None, - }) self.assertTrue(res['correct']) self.assertEqual(res['grade'], self.block.weight) + expected_calls = [ + mock.call(self.block, 'grade', { + 'value': 1, + 'max_value': 1, + 'only_if_higher': None, + }), + mock.call(self.block, 'progress', {}) + ] + self.assertEqual(patched_publish.mock_calls, expected_calls) + @ddt.data(*[random.randint(1, 50) for _ in xrange(5)]) # pylint: disable=star-args def test_do_attempt_incorrect_publish_grade(self, weight): self.block.weight = weight @@ -423,14 +428,19 @@ def test_do_attempt_incorrect_publish_grade(self, weight): res = self.call_handler(self.DO_ATTEMPT_HANDLER, data={}) self.assertFalse(self.block.completed) - patched_publish.assert_called_once_with(self.block, 'grade', { - 'value': correctness, - 'max_value': 1, - 'only_if_higher': None, - }) self.assertFalse(res['correct']) self.assertEqual(res['grade'], correctness * self.block.weight) + expected_calls = [ + mock.call(self.block, 'grade', { + 'value': correctness, + 'max_value': 1, + 'only_if_higher': None, + }), + mock.call(self.block, 'progress', {}) + ] + self.assertEqual(patched_publish.mock_calls, expected_calls) + @ddt.data(*[random.randint(1, 50) for _ in xrange(5)]) # pylint: disable=star-args def test_do_attempt_post_correct_no_publish_grade(self, weight): self.block.weight = weight @@ -444,7 +454,7 @@ def test_do_attempt_post_correct_no_publish_grade(self, weight): self.assertTrue(self.block.completed) self.assertEqual(self.block.raw_earned, 1) - self.assertFalse(patched_publish.called) + self.assertEqual(patched_publish.mock_calls, [mock.call(self.block, 'progress', {})]) def test_get_user_state_finished_after_final_attempt(self): self._set_final_attempt() @@ -469,11 +479,6 @@ def test_do_attempt_incorrect_final_attempt_publish_grade(self, weight): res = self.call_handler(self.DO_ATTEMPT_HANDLER, data={}) self.assertTrue(self.block.completed) - patched_publish.assert_called_once_with(self.block, 'grade', { - 'value': expected_raw_grade, - 'max_value': 1, - 'only_if_higher': None, - }) expected_grade_feedback = self._make_feedback_message( FeedbackMessages.FINAL_ATTEMPT_TPL.format(score=expected_weighted_grade), @@ -482,6 +487,16 @@ def test_do_attempt_incorrect_final_attempt_publish_grade(self, weight): self.assertIn(expected_grade_feedback, res[self.OVERALL_FEEDBACK_KEY]) self.assertEqual(res['grade'], expected_weighted_grade) + expected_calls = [ + mock.call(self.block, 'grade', { + 'value': expected_raw_grade, + 'max_value': 1, + 'only_if_higher': None, + }), + mock.call(self.block, 'progress', {}) + ] + self.assertEqual(patched_publish.mock_calls, expected_calls) + @ddt.data(*[random.randint(1, 50) for _ in xrange(5)]) # pylint: disable=star-args def test_do_attempt_incorrect_final_attempt_after_correct(self, weight): self.block.weight = weight @@ -505,9 +520,9 @@ def test_do_attempt_incorrect_final_attempt_after_correct(self, weight): FeedbackMessages.FINAL_ATTEMPT_TPL.format(score=float(weight)), FeedbackMessages.MessageClasses.PARTIAL_SOLUTION ) - self.assertFalse(patched_publish.called) self.assertIn(expected_grade_feedback, res[self.OVERALL_FEEDBACK_KEY]) self.assertEqual(self.block.raw_earned, 1) + self.assertEqual(patched_publish.mock_calls, [mock.call(self.block, 'progress', {})]) def test_do_attempt_misplaced_ids(self): misplaced_ids = self._submit_incorrect_solution()