def test_completion(self): user_id = 1 workgroups_to_review = OTHER_GROUPS.keys() expected_submissions = { "group_score": "100", "group_q1": "Y", "group_q2": "200" } stage_element = self.get_stage(self.go_to_view(student_id=user_id)) self.project_api_mock.get_workgroup_review_items_for_group.return_value = [ { "question": question, "answer": answer, "workgroup": group_id, "reviewer": str(reviewer_id), "content_id": self.activity_id, } for question, answer in expected_submissions.iteritems() for group_id in workgroups_to_review for reviewer_id in KNOWN_USERS.keys() ] group = stage_element.groups[0] self.select_review_subject(group) questions = stage_element.form.questions questions[0].control.select_option(expected_submissions["group_score"]) questions[1].control.select_option(expected_submissions["group_q1"]) questions[2].control.fill_text(expected_submissions["group_q2"]) self.submit_and_assert_completion_published(stage_element, user_id)
def test_completion(self): user_id = 1 other_users = set(KNOWN_USERS.keys()) - {user_id} expected_submissions = { "peer_score": "10", "peer_q1": "Y", "peer_q2": "Awesome" } stage_element = self.get_stage(self.go_to_view(student_id=user_id)) self.project_api_mock.get_peer_review_items_for_group.return_value = [ { "question": question, "answer": answer, "workgroup": 1, "user": peer_id, "reviewer": str(user_id), "content_id": self.activity_id, } for question, answer in expected_submissions.iteritems() for peer_id in other_users ] peer = stage_element.peers[0] self.select_review_subject(peer) questions = stage_element.form.questions self.wait_for_ajax() questions[0].control.select_option(expected_submissions["peer_score"]) questions[1].control.select_option(expected_submissions["peer_q1"]) questions[2].control.fill_text(expected_submissions["peer_q2"]) self.submit_and_assert_completion_published(stage_element, user_id)
def setUp(self): super(BasePeerReviewStageTest, self).setUp() self.project_api_mock.get_workgroups_to_review = mock.Mock( return_value=OTHER_GROUPS.values()) self.project_api_mock.get_workgroup_reviewers = mock.Mock( return_value=[{ "id": user.id } for user in KNOWN_USERS.values()])
def setUp(self): super(TestOtherGroupSubmissionLinks, self).setUp() self.project_api_mock.get_workgroups_to_review = mock.Mock( return_value=OTHER_GROUPS.values()) self.project_api_mock.get_workgroup_reviewers = mock.Mock( return_value=[{ "id": user.id } for user in KNOWN_USERS.values()])
def test_submission(self, user_id): self.make_patch(TeamEvaluationStage, 'anonymous_student_id', str(user_id)) stage_element = self.get_stage(self.go_to_view(student_id=user_id)) self._setup_review_items_store() initial_statuses = { usr_id: ReviewState.NOT_STARTED for usr_id in list(KNOWN_USERS.keys()) if usr_id != user_id } self._assert_teammate_statuses(stage_element, initial_statuses) # precondition check peer = stage_element.peers[0] self.select_review_subject(peer) expected_submissions = { "peer_score": "10", "peer_q1": "Y", "peer_q2": "Awesome" } questions = stage_element.form.questions questions[0].control.select_option(expected_submissions["peer_score"]) questions[1].control.select_option(expected_submissions["peer_q1"]) questions[2].control.fill_text(expected_submissions["peer_q2"]) self.assertTrue(stage_element.form.submit.is_displayed()) self.assertEqual(stage_element.form.submit.text, "Submit") # first time here - should read Submit self.click_submit(stage_element) self.project_api_mock.submit_peer_review_items.assert_called_once_with( str(user_id), stage_element.form.peer_id, 1, self.activity_id, expected_submissions) expected_statuses = { usr_id: ReviewState.NOT_STARTED for usr_id in KNOWN_USERS.keys() if usr_id != user_id } expected_statuses[int( peer.subject_id )] = ReviewState.COMPLETED # status is refreshed after submission self._assert_teammate_statuses(stage_element, expected_statuses)
def test_interaction(self, user_id): stage_element = self.get_stage(self.go_to_view(student_id=user_id)) other_users = set(KNOWN_USERS.keys()) - {user_id} # A default selection should be made automatically. self.assertEquals(stage_element.form.peer_id, min(other_users)) peers = stage_element.peers self.assertEqual(len(peers), len(other_users)) for user_id, peer in zip(other_users, peers): self.assertEqual(peer.name, KNOWN_USERS[user_id].username) self.select_review_subject(peer) self.assertEqual(stage_element.form.peer_id, user_id)
def test_submission(self, user_id): stage_element = self.get_stage(self.go_to_view(student_id=user_id)) self._setup_review_items_store() initial_statuses = {usr_id: ReviewState.NOT_STARTED for usr_id in KNOWN_USERS.keys() if usr_id != user_id} self._assert_teammate_statuses(stage_element, initial_statuses) # precondition check peer = stage_element.peers[0] self.select_review_subject(peer) expected_submissions = { "peer_score": "10", "peer_q1": "Y", "peer_q2": "Awesome" } questions = stage_element.form.questions questions[0].control.select_option(expected_submissions["peer_score"]) questions[1].control.select_option(expected_submissions["peer_q1"]) questions[2].control.fill_text(expected_submissions["peer_q2"]) self.assertTrue(stage_element.form.submit.is_displayed()) self.assertEqual(stage_element.form.submit.text, "Submit") # first time here - should read Submit self.click_submit(stage_element) self.project_api_mock.submit_peer_review_items.assert_called_once_with( str(user_id), stage_element.form.peer_id, 1, self.activity_id, expected_submissions ) expected_statuses = {usr_id: ReviewState.NOT_STARTED for usr_id in KNOWN_USERS.keys() if usr_id != user_id} expected_statuses[int(peer.subject_id)] = ReviewState.COMPLETED # status is refreshed after submission self._assert_teammate_statuses(stage_element, expected_statuses)
def setUp(self): super(TestOtherGroupSubmissionLinks, self).setUp() self.project_api_mock.get_workgroups_to_review = mock.Mock(return_value=OTHER_GROUPS.values()) self.project_api_mock.get_workgroup_reviewers = mock.Mock(return_value=[ {"id": user.id} for user in KNOWN_USERS.values() ])
class TeamEvaluationStageTest(BaseReviewStageTest): stage_type = TeamEvaluationStage stage_element = ReviewStageElement STAGE_DATA_XML = textwrap.dedent(""" <gp-v2-peer-selector/> <gp-v2-review-question question_id="peer_score" title="How about that?" required="true" single_line="true"> <opt:question_content> <![CDATA[ <select> <option value="">Rating</option> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> <option value="7">7</option> <option value="8">8</option> <option value="9">9</option> <option value="10">10</option> </select> ]]> </opt:question_content> </gp-v2-review-question> <gp-v2-review-question question_id="peer_q1" title="Were they helpful?" required="true" single_line="true"> <opt:question_content> <![CDATA[ <select> <option value="Y">Yes</option> <option value="N">No</option> </select> ]]> </opt:question_content> </gp-v2-review-question> <gp-v2-review-question question_id="peer_q2" title="General Comments" required="false"> <opt:question_content> <![CDATA[ <textarea/> ]]> </opt:question_content> </gp-v2-review-question> """) REQUIRED_QUESTION_ID1 = "peer_score" REQUIRED_QUESTION_ID2 = "peer_q1" def setUp(self): super(TeamEvaluationStageTest, self).setUp() self.project_api_mock.get_peer_review_items = mock.Mock( return_value={}) self.load_scenario_xml(self.build_scenario_xml(self.STAGE_DATA_XML), load_immediately=False) def _setup_review_items_store(self, initial_items=None): store = defaultdict(list) if initial_items: store.update(initial_items) def get_review_items(_reviewer_id, peer_id, _group_id, _content_id): return store.get(peer_id, []) def submit_peer_review_items(reviewer_id, peer_id, group_id, content_id, data): new_items = [ mri(reviewer_id, question_id, peer=peer_id, content_id=content_id, answer=answer, group=group_id) for question_id, answer in data.iteritems() if len(answer) > 0 ] store[peer_id].extend(new_items) self.project_api_mock.get_peer_review_items = mock.Mock( side_effect=get_review_items) self.project_api_mock.submit_peer_review_items = mock.Mock( side_effect=submit_peer_review_items) def _assert_teammate_statuses(self, stage_element, expected_statuses): teammate_statuses = { int(peer.subject_id): peer.review_status for peer in stage_element.peers } self.assertEqual(teammate_statuses, expected_statuses) def test_rendering_questions(self): stage_element = self.get_stage(self.go_to_view()) expected_options = {str(idx): str(idx) for idx in xrange(1, 11)} expected_options.update({"": "Rating"}) questions = stage_element.form.questions self.assertEqual(questions[0].label, "How about that?") self.assertEqual(questions[0].control.name, "peer_score") self.assertEqual(questions[0].control.tag_name, "select") self.assertEqual(questions[0].control.options, expected_options) self.assertEqual(questions[1].label, "Were they helpful?") self.assertEqual(questions[1].control.name, "peer_q1") self.assertEqual(questions[1].control.tag_name, "select") self.assertEqual(questions[1].control.options, {"Y": "Yes", "N": "No"}) self.assertEqual(questions[2].label, "General Comments") self.assertEqual(questions[2].control.name, "peer_q2") self.assertEqual(questions[2].control.tag_name, "textarea") def test_teammate_review_statuses(self): user_id = TestConstants.Users.USER1_ID reviews = { TestConstants.Users.USER2_ID: [ mri(user_id, self.REQUIRED_QUESTION_ID1, peer=TestConstants.Users.USER2_ID, answer='not empty'), ], TestConstants.Users.USER3_ID: [ mri(user_id, self.REQUIRED_QUESTION_ID1, peer=TestConstants.Users.USER3_ID, answer='not empty'), mri(user_id, self.REQUIRED_QUESTION_ID2, peer=TestConstants.Users.USER3_ID, answer='other') ], } self._setup_review_items_store(reviews) stage_element = self.get_stage(self.go_to_view(student_id=user_id)) expected_statuses = { TestConstants.Users.USER2_ID: ReviewState.INCOMPLETE, TestConstants.Users.USER3_ID: ReviewState.COMPLETED } self._assert_teammate_statuses(stage_element, expected_statuses) @ddt.data(*KNOWN_USERS.keys()) # pylint: disable=star-args def test_interaction(self, user_id): stage_element = self.get_stage(self.go_to_view(student_id=user_id)) other_users = set(KNOWN_USERS.keys()) - {user_id} # A default selection should be made automatically. self.assertEquals(stage_element.form.peer_id, min(other_users)) peers = stage_element.peers self.assertEqual(len(peers), len(other_users)) for user_id, peer in zip(other_users, peers): self.assertEqual(peer.name, KNOWN_USERS[user_id].username) self.select_review_subject(peer) self.assertEqual(stage_element.form.peer_id, user_id) @ddt.data(*KNOWN_USERS.keys()) # pylint: disable=star-args def test_submission(self, user_id): stage_element = self.get_stage(self.go_to_view(student_id=user_id)) self._setup_review_items_store() initial_statuses = { usr_id: ReviewState.NOT_STARTED for usr_id in KNOWN_USERS.keys() if usr_id != user_id } self._assert_teammate_statuses(stage_element, initial_statuses) # precondition check peer = stage_element.peers[0] self.select_review_subject(peer) expected_submissions = { "peer_score": "10", "peer_q1": "Y", "peer_q2": "Awesome" } questions = stage_element.form.questions questions[0].control.select_option(expected_submissions["peer_score"]) questions[1].control.select_option(expected_submissions["peer_q1"]) questions[2].control.fill_text(expected_submissions["peer_q2"]) self.assertTrue(stage_element.form.submit.is_displayed()) self.assertEqual(stage_element.form.submit.text, "Submit") # first time here - should read Submit self.click_submit(stage_element) self.project_api_mock.submit_peer_review_items.assert_called_once_with( str(user_id), stage_element.form.peer_id, 1, self.activity_id, expected_submissions) expected_statuses = { usr_id: ReviewState.NOT_STARTED for usr_id in KNOWN_USERS.keys() if usr_id != user_id } expected_statuses[int( peer.subject_id )] = ReviewState.COMPLETED # status is refreshed after submission self._assert_teammate_statuses(stage_element, expected_statuses) def test_persistence_and_resubmission(self): user_id = 1 expected_submissions = { "peer_score": "10", "peer_q1": "Y", "peer_q2": "Awesome" } self.project_api_mock.get_peer_review_items.return_value = [{ "question": question, "answer": answer, "user": TestConstants.Users.USER2_ID } for question, answer in expected_submissions.iteritems()] stage_element = self.get_stage(self.go_to_view(student_id=user_id)) peer = stage_element.peers[0] self.select_review_subject(peer) # loading peer review items from project_api self.project_api_mock.get_peer_review_items.assert_called_with( str(user_id), stage_element.form.peer_id, 1, self.activity_id, ) questions = stage_element.form.questions self.assertEqual(questions[0].control.value, expected_submissions["peer_score"]) self.assertEqual(questions[1].control.value, expected_submissions["peer_q1"]) self.assertEqual(questions[2].control.value, expected_submissions["peer_q2"]) new_submissions = { "peer_score": "2", "peer_q1": "N", "peer_q2": "Awful" } questions[0].control.select_option(new_submissions["peer_score"]) questions[1].control.select_option(new_submissions["peer_q1"]) questions[2].control.fill_text(new_submissions["peer_q2"]) self.assertEqual(stage_element.form.submit.text, "Resubmit") self.click_submit(stage_element) self.project_api_mock.submit_peer_review_items.assert_called_once_with( str(user_id), stage_element.form.peer_id, 1, self.activity_id, new_submissions) def test_completion(self): user_id = 1 other_users = set(KNOWN_USERS.keys()) - {user_id} expected_submissions = { "peer_score": "10", "peer_q1": "Y", "peer_q2": "Awesome" } stage_element = self.get_stage(self.go_to_view(student_id=user_id)) self.project_api_mock.get_peer_review_items_for_group.return_value = [ { "question": question, "answer": answer, "workgroup": 1, "user": peer_id, "reviewer": str(user_id), "content_id": self.activity_id, } for question, answer in expected_submissions.iteritems() for peer_id in other_users ] peer = stage_element.peers[0] self.select_review_subject(peer) questions = stage_element.form.questions self.wait_for_ajax() questions[0].control.select_option(expected_submissions["peer_score"]) questions[1].control.select_option(expected_submissions["peer_q1"]) questions[2].control.fill_text(expected_submissions["peer_q2"]) self.submit_and_assert_completion_published(stage_element, user_id)
def setUp(self): super(BasePeerReviewStageTest, self).setUp() self.project_api_mock.get_workgroups_to_review = mock.Mock(return_value=OTHER_GROUPS.values()) self.project_api_mock.get_workgroup_reviewers = mock.Mock(return_value=[ {"id": user.id} for user in KNOWN_USERS.values() ])
class TestBaseGroupActivityStage(BaseStageTest): """ Tests for Base Stage Class """ block_to_test = DummyStageBlock def setUp(self): super(TestBaseGroupActivityStage, self).setUp() self.render_template_patch = self.make_patch(self.block, 'render_template') # invalid name in order to match camlCase naming of assertSomething methods def assertDictionaryEqual(self, actual, expected, strict=False): # pylint: disable=invalid-name """ Less strict assert for dictionary equality - checks that `actual` contains all the keys from expected, and values match. If `strict` is true, also checks that no other keys are present in the `actual` (roughly equal to plain assertEqual) :param dict[Any, Any] actual: actual result :param dict[Any, ANy] expected: expected result :param bool strict: Strict comparison: If set to False allows `actual` to contain keys not found in `expected`. If True - requires that no other keys are present in `actual` - roughly equivalent to plain assertEqual """ for key, value in expected.iteritems(): self.assertIn(key, actual) self.assertEqual(actual[key], value) if strict: self.assertEqual(actual.keys(), expected.keys()) @ddt.data( ([WORKGROUP], KNOWN_USERS.values(), StageState.COMPLETED, make_stats(1.0, 0, 0)), ([WORKGROUP], KNOWN_USERS.values(), StageState.INCOMPLETE, make_stats(0.3, 0.4, 0.3)), (OTHER_GROUPS, KNOWN_USERS.values(), StageState.INCOMPLETE, make_stats(0.3, 0.4, 0.3)), (OTHER_GROUPS, KNOWN_USERS.values(), StageState.NOT_STARTED, make_stats(0.0, 0.0, 1.0)), ) @ddt.unpack def test_dashboard_view(self, workgroups, target_students, state, stats): render_template_response = u'render_template_response' is_ta_graded = False patched_stats = self.make_patch(self.block, 'get_dashboard_stage_state') patched_stats.return_value = (state, stats) type(self.activity_mock).is_ta_graded = mock.PropertyMock( return_value=is_ta_graded) self.render_template_patch.return_value = render_template_response context = make_context(workgroups, target_students, []) expected_human_stats = get_human_stats(stats[StageState.COMPLETED], stats[StageState.INCOMPLETE], stats[StageState.NOT_STARTED]) expected_context = { 'stage': self.block, 'stats': expected_human_stats, 'stage_state': state, 'ta_graded': is_ta_graded } with mock.patch('group_project_v2.stage.base.Fragment.add_content' ) as patched_add_content: self.block.dashboard_view(context) patched_add_content.assert_called_once_with( render_template_response) # single call - roughly equivalent to assert_called_once_with(...) self.assertEqual(len(self.render_template_patch.call_args_list), 1) args, kwargs = self.render_template_patch.call_args_list[0] self.assertEqual(kwargs, {}) self.assertEqual(len(args), 2) self.assertEqual(args[0], 'dashboard_view') self.assertDictionaryEqual(args[1], expected_context) @ddt.data( # not filtered - pass all students ([WORKGROUP], KNOWN_USERS.values(), [], KNOWN_USERS.values()), # single filter hit - pass all except that student ([WORKGROUP], KNOWN_USERS.values(), [TEST_USERS.USER1_ID], [KNOWN_USERS[TEST_USERS.USER2_ID], KNOWN_USERS[TEST_USERS.USER3_ID]]), # multiple filter hits - pass all except that students ([WORKGROUP], KNOWN_USERS.values(), [ TEST_USERS.USER1_ID, TEST_USERS.USER3_ID ], [KNOWN_USERS[TEST_USERS.USER2_ID]]), # filter "miss" - pass all ([WORKGROUP], KNOWN_USERS.values(), [TEST_USERS.UNKNOWN_USER ], KNOWN_USERS.values()), # filter hit and miss - pass all expcept hit ([WORKGROUP], KNOWN_USERS.values(), [TEST_USERS.USER2_ID, TEST_USERS.UNKNOWN_USER], [KNOWN_USERS[TEST_USERS.USER1_ID], KNOWN_USERS[TEST_USERS.USER3_ID]]), # filtered all - pass no students ([WORKGROUP], KNOWN_USERS.values(), [TEST_USERS.USER1_ID, TEST_USERS.USER2_ID, TEST_USERS.USER3_ID], []), ) @ddt.unpack def test_dashboard_view_filters_students(self, workgroups, target_students, filtered_students, expected_students): patched_stats = self.make_patch(self.block, 'get_dashboard_stage_state') patched_stats.return_value = (StageState.COMPLETED, make_stats(1.0, 0.0, 0.0)) context = make_context(workgroups, target_students, filtered_students) with mock.patch('group_project_v2.stage.base.Fragment.add_content'): self.block.dashboard_view(context) patched_stats.assert_called_once_with(workgroups, expected_students) def test_get_external_group_status(self): self.assertEqual(self.block.get_external_group_status('irrelevant'), StageState.NOT_AVAILABLE) def test_get_external_status_label(self): self.assertEqual(self.block.get_external_status_label('irrelevant'), self.block.DEFAULT_EXTERNAL_STATUS_LABEL)
class TestBaseGroupActivityStage(BaseStageTest): """ Tests for Base Stage Class """ block_to_test = DummyStageBlock def setUp(self): super(TestBaseGroupActivityStage, self).setUp() self.render_template_patch = self.make_patch(self.block, 'render_template') def test_stage_is_not_graded(self): self.assertFalse(self.block.is_graded_stage) def test_stage_is_not_shown_on_detail_dashboard(self): self.assertFalse(self.block.shown_on_detail_view) # invalid name in order to match camlCase naming of assertSomething methods def assertDictionaryEqual(self, actual, expected, strict=False): # pylint: disable=invalid-name """ Less strict assert for dictionary equality - checks that `actual` contains all the keys from expected, and values match. If `strict` is true, also checks that no other keys are present in the `actual` (roughly equal to plain assertEqual) :param dict[Any, Any] actual: actual result :param dict[Any, ANy] expected: expected result :param bool strict: Strict comparison: If set to False allows `actual` to contain keys not found in `expected`. If True - requires that no other keys are present in `actual` - roughly equivalent to plain assertEqual """ for key, value in expected.iteritems(): self.assertIn(key, actual) self.assertEqual(actual[key], value) if strict: self.assertEqual(actual.keys(), expected.keys()) @ddt.data( ([WORKGROUP], KNOWN_USERS.values(), StageState.COMPLETED, make_stats(1.0, 0, 0)), ([WORKGROUP], KNOWN_USERS.values(), StageState.INCOMPLETE, make_stats(0.3, 0.4, 0.3)), (OTHER_GROUPS, KNOWN_USERS.values(), StageState.INCOMPLETE, make_stats(0.3, 0.4, 0.3)), (OTHER_GROUPS, KNOWN_USERS.values(), StageState.NOT_STARTED, make_stats(0.0, 0.0, 1.0)), ) @ddt.unpack def test_dashboard_view(self, workgroups, target_students, state, stats): render_template_response = u'render_template_response' is_ta_graded = False patched_stats = self.make_patch(self.block, 'get_dashboard_stage_state') patched_stats.return_value = (state, stats) type(self.activity_mock).is_ta_graded = mock.PropertyMock( return_value=is_ta_graded) self.render_template_patch.return_value = render_template_response context = make_context(workgroups, target_students, []) expected_human_stats = BaseGroupActivityStage.make_human_stats(stats) expected_context = { 'stage': self.block, 'stats': expected_human_stats, 'stage_state': state, 'ta_graded': is_ta_graded } with mock.patch('group_project_v2.stage.base.Fragment.add_content' ) as patched_add_content: self.block.dashboard_view(context) patched_add_content.assert_called_once_with( render_template_response) # single call - roughly equivalent to assert_called_once_with(...) self.assertEqual(len(self.render_template_patch.call_args_list), 1) args, kwargs = self.render_template_patch.call_args_list[0] self.assertEqual(kwargs, {}) self.assertEqual(len(args), 2) self.assertEqual(args[0], 'dashboard_view') self.assertDictionaryEqual(args[1], expected_context) @ddt.data((make_stats(0.4, 0.3, 0.4), (40, 30, 40)), (make_stats(0.1, 0.1, 0.8), (80, 10, 10)), (make_stats(None, None, None), (None, None, None))) @ddt.unpack def test_make_human_stats(self, stats, human_stats_data): stats_order = (StageState.NOT_STARTED, StageState.INCOMPLETE, StageState.COMPLETED) actual_human_stats = BaseGroupActivityStage.make_human_stats(stats) expected_human_stats = OrderedDict([ (StageState.get_human_name(stats_order[idx]), human_stats_data[idx]) for idx in range(3) ]) self.assertEqual(actual_human_stats.keys(), expected_human_stats.keys()) for idx, human_stat in enumerate(expected_human_stats.items()): stat_name, stat_value = human_stat actual_stat_value = actual_human_stats[stat_name] self.assertAlmostEqual(stat_value, actual_stat_value) @ddt.data( # not filtered - pass all students ([WORKGROUP], KNOWN_USERS.values(), [], KNOWN_USERS.values()), # single filter hit - pass all except that student ([WORKGROUP], KNOWN_USERS.values(), [TEST_USERS.USER1_ID], [KNOWN_USERS[TEST_USERS.USER2_ID], KNOWN_USERS[TEST_USERS.USER3_ID]]), # multiple filter hits - pass all except that students ([WORKGROUP], KNOWN_USERS.values(), [ TEST_USERS.USER1_ID, TEST_USERS.USER3_ID ], [KNOWN_USERS[TEST_USERS.USER2_ID]]), # filter "miss" - pass all ([WORKGROUP], KNOWN_USERS.values(), [TEST_USERS.UNKNOWN_USER ], KNOWN_USERS.values()), # filter hit and miss - pass all expcept hit ([WORKGROUP], KNOWN_USERS.values(), [TEST_USERS.USER2_ID, TEST_USERS.UNKNOWN_USER], [KNOWN_USERS[TEST_USERS.USER1_ID], KNOWN_USERS[TEST_USERS.USER3_ID]]), # filtered all - pass no students ([WORKGROUP], KNOWN_USERS.values(), [TEST_USERS.USER1_ID, TEST_USERS.USER2_ID, TEST_USERS.USER3_ID], []), ) @ddt.unpack def test_dashboard_view_filters_students(self, workgroups, target_students, filtered_students, expected_students): patched_stats = self.make_patch(self.block, 'get_dashboard_stage_state') patched_stats.return_value = (StageState.COMPLETED, make_stats(1.0, 0.0, 0.0)) context = make_context(workgroups, target_students, filtered_students) with mock.patch('group_project_v2.stage.base.Fragment.add_content'): self.block.dashboard_view(context) patched_stats.assert_called_once_with(workgroups, expected_students) @ddt.data( ([1], [1], [], make_stats(1, 0, 0), True), (range(10), range(3), range(3, 6), make_stats(.3, .3, .4), True), ([], [], [], make_stats(None, None, None), False), ) @ddt.unpack def test_get_stage_stats(self, all_user_ids, completed_user_ids, partial_user_ids, expected_stats, completions_called): all_users = [ make_reduced_user_details(id=user_id) for user_id in all_user_ids ] completed_user_ids = set(completed_user_ids) partial_user_ids = set(partial_user_ids) patched_completions = self.make_patch(self.block, 'get_users_completion') self.block.display_name = "dummy block" patched_completions.return_value = (completed_user_ids, partial_user_ids) target_workgroups = tuple() stats = self.block.get_stage_stats(target_workgroups, all_users) if completions_called: patched_completions.assert_called_once_with( target_workgroups, all_users) else: self.assertFalse(patched_completions.called) self.assertEqual(len(expected_stats), len(stats)) for stat, value in stats.items(): self.assertAlmostEqual(value, expected_stats[stat]) def test_get_external_group_status(self): self.assertEqual(self.block.get_external_group_status('irrelevant'), StageState.NOT_AVAILABLE) def test_get_external_status_label(self): self.assertEqual(self.block.get_external_status_label('irrelevant'), self.block.DEFAULT_EXTERNAL_STATUS_LABEL)