From c1b6eeaf663a6fdef921a9cb6d54b24da8bba28d Mon Sep 17 00:00:00 2001 From: leangseu-edx <83240113+leangseu-edx@users.noreply.github.com> Date: Thu, 16 Nov 2023 10:15:18 -0500 Subject: [PATCH] fix: active step name for waiting learner (#2112) * chore: respond step name for waiting chore: linting * fix: code review comments * chore: version --------- Co-authored-by: jansenk --- .../ui_mixins/mfe/page_context_serializer.py | 16 +++++ .../mfe/test_page_context_serializer.py | 64 +++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/openassessment/xblock/ui_mixins/mfe/page_context_serializer.py b/openassessment/xblock/ui_mixins/mfe/page_context_serializer.py index 3bb623682b..cad32e865b 100644 --- a/openassessment/xblock/ui_mixins/mfe/page_context_serializer.py +++ b/openassessment/xblock/ui_mixins/mfe/page_context_serializer.py @@ -22,6 +22,10 @@ from openassessment.xblock.ui_mixins.mfe.serializer_utils import STEP_NAME_MAPPINGS, CharListField +class UnknownActiveStepException(Exception): + """Raised when we can't determine the active step""" + + class AssessmentScoreSerializer(Serializer): """ Returns: @@ -246,6 +250,18 @@ def get_activeStepName(self, instance): """Return the active step name""" if not instance.workflow_data.has_workflow or instance.workflow_data.is_cancelled: return "submission" + elif instance.workflow_data.is_waiting: + # If we are waiting, we are either waiting on a peer or a staff grade. + # Staff takes precidence, so if a required (not automatically inserted) staff + # step exists, we are considered to be in "staff". If there is a peer, we are + # considered to be in "peer" + workflow_requirements = instance.workflow_data.workflow_requirements + if "staff" in workflow_requirements and workflow_requirements["staff"]["required"]: + return "staff" + elif "peer" in workflow_requirements: + return "peer" + else: + raise UnknownActiveStepException("Workflow is in waiting but no staff or peer step is required.") else: return STEP_NAME_MAPPINGS[instance.workflow_data.status] diff --git a/openassessment/xblock/ui_mixins/mfe/test_page_context_serializer.py b/openassessment/xblock/ui_mixins/mfe/test_page_context_serializer.py index 7919ebf86e..184b40e9b3 100644 --- a/openassessment/xblock/ui_mixins/mfe/test_page_context_serializer.py +++ b/openassessment/xblock/ui_mixins/mfe/test_page_context_serializer.py @@ -14,6 +14,7 @@ from openassessment.workflow.api import cancel_workflow from openassessment.xblock.apis.submissions.submissions_actions import create_team_submission from openassessment.xblock.apis.submissions.submissions_api import SubmissionAPI +from openassessment.xblock.apis.workflow_api import WorkflowAPI from openassessment.xblock.test.base import ( PEER_ASSESSMENTS, SELF_ASSESSMENT, @@ -26,6 +27,7 @@ PageDataSerializer, ProgressSerializer, TeamInfoSerializer, + UnknownActiveStepException, ) @@ -455,6 +457,25 @@ def test_peer_assessment(self, xblock): self.assertNestedDictEquals(expected_data, progress_data) + @scenario("data/grade_scenario_peer_only.xml", user_id="Alan") + def test_peer_assessment__waiting(self, xblock): + # Given I am on the peer step and waiting for submissions + self.create_submission_and_assessments( + xblock, + 'submission_text', + self.PEERS, + PEER_ASSESSMENTS, + None, + waiting_for_peer=True + ) + self.assertTrue(xblock.workflow_data.is_waiting) + + # When I ask for progress + progress_data = ProgressSerializer(xblock).data + + # Expect active step to be peer instead of waiting + self.assertEqual('peer', progress_data['activeStepName']) + @scenario("data/peer_only_scenario.xml", user_id="Alan") def test_peer_assessment__cancelled(self, xblock): # Given I am on the peer step and then get cancelled @@ -586,6 +607,49 @@ def test_self_assessment_not_available(self, xblock): self.assertNestedDictEquals(expected_data, progress_data) + @scenario('data/grade_scenario_self_staff.xml', user_id='Alan') + def test_self_staff_assessment__waiting(self, xblock): + # Given I am on the staff step and waiting for submissions + self.create_submission_and_assessments(xblock, 'submission_text', [], [], SELF_ASSESSMENT) + self.assertTrue(xblock.workflow_data.is_waiting) + + # When I ask for progress + progress_data = ProgressSerializer(xblock).data + + # Expect active step to be staff instead of waiting + self.assertEqual('staff', progress_data['activeStepName']) + + @scenario("data/grade_scenario_staff_peer.xml", user_id="Alan") + def test_peer_the_staff_assessment__waiting(self, xblock): + # Given I am waiting for both peer and staff assessments + self.create_submission_and_assessments( + xblock, + 'submission_text', + self.PEERS, + PEER_ASSESSMENTS, + None, + waiting_for_peer=True + ) + self.assertTrue(xblock.workflow_data.is_waiting) + + # When I ask for progress + progress_data = ProgressSerializer(xblock).data + + # Expect active step to be staff instead of waiting or peer + self.assertEqual('staff', progress_data['activeStepName']) + + @scenario("data/self_only_scenario.xml", user_id="Alan") + def test_waiting_error(self, xblock): + # Given I am waiting when I shouldn't be able to be waiting + self.create_test_submission(xblock) + self.assertTrue(xblock.workflow_data.is_self) + + with patch.object(WorkflowAPI, 'is_waiting', new_callable=PropertyMock(return_value=True)): + self.assertTrue(xblock.workflow_data.is_waiting) + # When I ask for progress + with self.assertRaises(UnknownActiveStepException): + ProgressSerializer(xblock).data # pylint: disable=expression-not-assigned + @skip @scenario("data/team_submission.xml", user_id="Alan") def test_team_assignment(self, xblock):