diff --git a/autograder/core/models/group/group.py b/autograder/core/models/group/group.py index 5a1caebe..77a175d8 100644 --- a/autograder/core/models/group/group.py +++ b/autograder/core/models/group/group.py @@ -213,8 +213,8 @@ def clean(self) -> None: 'Hard extended due date must be a valid date')}) except core_ut.HardDeadlineBeforeSoftDeadlineError: raise ValidationError( - {'soft_extended_due_date': ( - 'Soft extended due date must not be after hard extended due date')}) + {'hard_extended_due_date': ( + 'Hard extended due date must not be before soft extended due date')}) self.soft_extended_due_date = clean_soft self.hard_extended_due_date = clean_hard diff --git a/autograder/core/models/project/project.py b/autograder/core/models/project/project.py index 4624616d..6cc13b98 100644 --- a/autograder/core/models/project/project.py +++ b/autograder/core/models/project/project.py @@ -251,8 +251,8 @@ def clean(self) -> None: 'Closing time must be a valid date')}) except core_ut.HardDeadlineBeforeSoftDeadlineError: raise exceptions.ValidationError( - {'soft_closing_time': ( - 'Soft closing time must not be after hard closing time')}) + {'closing_time': ( + 'Closing time must not be before soft closing time')}) self.soft_closing_time = clean_soft self.closing_time = clean_hard diff --git a/autograder/rest_api/tests/test_views/ag_view_test_base.py b/autograder/rest_api/tests/test_views/ag_view_test_base.py index e1aa0044..f8549afd 100644 --- a/autograder/rest_api/tests/test_views/ag_view_test_base.py +++ b/autograder/rest_api/tests/test_views/ag_view_test_base.py @@ -92,9 +92,7 @@ def do_patch_object_test(self, ag_model_obj, client, user, url, ignore_fields = list(ignore_fields) ignore_fields.append('last_modified') - expected_data = ag_model_obj.to_dict() - for field in ignore_fields: - expected_data.pop(field, None) + expected_data = utils.exclude_dict(ag_model_obj.to_dict(), ignore_fields) for key, value in request_data.items(): if isinstance(value, dict): expected_data[key].update(value) @@ -171,9 +169,6 @@ def _do_bad_update_test(self, ag_model_obj, client, user, url, request_data, self.assertEqual(expected_status, response.status_code) ag_model_obj = ag_model_obj._meta.model.objects.get(pk=ag_model_obj.pk) - - print(f"{expected_data=}") - print(f"{ag_model_obj.to_dict()=}") self.assert_dict_contents_equal(expected_data, ag_model_obj.to_dict()) return response diff --git a/autograder/rest_api/tests/test_views/test_group_views/test_group_views.py b/autograder/rest_api/tests/test_views/test_group_views/test_group_views.py index fa520eeb..f40fb8f2 100644 --- a/autograder/rest_api/tests/test_views/test_group_views/test_group_views.py +++ b/autograder/rest_api/tests/test_views/test_group_views/test_group_views.py @@ -483,6 +483,12 @@ def test_admin_update_guest_group_members(self): def test_admin_update_group_deprecated_extended_due_date(self): group = obj_build.make_group(project=self.project) + invalid_extended_due_date = "not a date" + response = self.do_patch_object_invalid_args_test( + group, self.client, self.admin, self.group_url(group), + {'extended_due_date': invalid_extended_due_date}) + self.assertIn('soft_extended_due_date', response.data) + self.do_patch_object_test( group, self.client, self.admin, self.group_url(group), {'extended_due_date': self.new_due_date}, @@ -498,6 +504,20 @@ def test_admin_update_group_deprecated_extended_due_date(self): def test_admin_update_soft_extended_due_date(self): group = obj_build.make_group( project=self.project, hard_extended_due_date=self.new_due_date) + + invalid_soft_extended_due_date = "not a date" + response = self.do_patch_object_invalid_args_test( + group, self.client, self.admin, self.group_url(group), + {'soft_extended_due_date': invalid_soft_extended_due_date}) + self.assertIn('soft_extended_due_date', response.data) + + # soft_extended_due_date can't be later than hard_extended_due_date + invalid_soft_extended_due_date = self.new_due_date + datetime.timedelta(days=1) + response = self.do_patch_object_invalid_args_test( + group, self.client, self.admin, self.group_url(group), + {'soft_extended_due_date': invalid_soft_extended_due_date}) + self.assertIn('hard_extended_due_date', response.data) + valid_soft_extended_due_date = self.new_due_date - datetime.timedelta(days=1) self.do_patch_object_test( group, self.client, self.admin, self.group_url(group), @@ -505,27 +525,29 @@ def test_admin_update_soft_extended_due_date(self): expected_response_overrides={ 'soft_extended_due_date': valid_soft_extended_due_date.replace( second=0, microsecond=0), - # extended_due_date is deprecated, should reflect changes to soft_extended_deadline + # setting soft_extended_due_date will also set extended_due_date + # for backwards compatibility 'extended_due_date': valid_soft_extended_due_date.replace( second=0, microsecond=0) }) - group.refresh_from_db() + def test_admin_update_hard_extended_due_date(self): + group = obj_build.make_group( + project=self.project, soft_extended_due_date=self.new_due_date) - invalid_soft_extended_due_date = "not a date" - self.do_patch_object_invalid_args_test( + invalid_hard_extended_due_date = "not a date" + response = self.do_patch_object_invalid_args_test( group, self.client, self.admin, self.group_url(group), - {'soft_extended_due_date': invalid_soft_extended_due_date}) + {'hard_extended_due_date': invalid_hard_extended_due_date}) + self.assertIn('hard_extended_due_date', response.data) - # soft_extended_due_date can't be later than hard_extended_due_date - invalid_soft_extended_due_date = self.new_due_date + datetime.timedelta(days=1) - self.do_patch_object_invalid_args_test( + # hard_extended_due_date can't be before soft_extended_due_date + invalid_hard_extended_due_date = self.new_due_date - datetime.timedelta(days=1) + response = self.do_patch_object_invalid_args_test( group, self.client, self.admin, self.group_url(group), - {'soft_extended_due_date': invalid_soft_extended_due_date}) + {'hard_extended_due_date': invalid_hard_extended_due_date}) + self.assertIn('hard_extended_due_date', response.data) - def test_admin_update_hard_extended_due_date(self): - group = obj_build.make_group( - project=self.project, soft_extended_due_date=self.new_due_date) valid_hard_extended_due_date = self.new_due_date + datetime.timedelta(days=1) self.do_patch_object_test( group, self.client, self.admin, self.group_url(group), @@ -538,19 +560,6 @@ def test_admin_update_hard_extended_due_date(self): second=0, microsecond=0) }) - group.refresh_from_db() - - invalid_hard_extended_due_date = "not a date" - self.do_patch_object_invalid_args_test( - group, self.client, self.admin, self.group_url(group), - {'hard_extended_due_date': invalid_hard_extended_due_date}) - - # hard_extended_due_date can't be before soft_extended_due_date - invalid_hard_extended_due_date = self.new_due_date - datetime.timedelta(days=1) - self.do_patch_object_invalid_args_test( - group, self.client, self.admin, self.group_url(group), - {'hard_extended_due_date': invalid_hard_extended_due_date}) - def test_admin_update_group_invalid_members(self): group = obj_build.make_group(project=self.project) new_members = self.get_names(list(group.members.all())[:-1]) + ['stove'] @@ -575,13 +584,6 @@ def test_admin_update_group_error_non_allowed_domain_guest(self): {'member_names': [allowed_guest.username, non_allowed_guest.username]}) self.assertIn('members', response.data) - def test_admin_update_group_bad_date(self): - group = obj_build.make_group(project=self.project) - response = self.do_patch_object_invalid_args_test( - group, self.client, self.admin, self.group_url(group), - {'extended_due_date': 'not a date'}) - self.assertIn('extended_due_date', response.data) - def test_non_admin_update_group_permission_denied(self): group = obj_build.make_group(project=self.project) staff = obj_build.make_staff_user(self.course) diff --git a/autograder/rest_api/tests/test_views/test_project_views/test_project_views.py b/autograder/rest_api/tests/test_views/test_project_views/test_project_views.py index 249c6e3d..cf23c574 100644 --- a/autograder/rest_api/tests/test_views/test_project_views/test_project_views.py +++ b/autograder/rest_api/tests/test_views/test_project_views/test_project_views.py @@ -249,8 +249,9 @@ def test_edit_project_invalid_closing_time(self): } admin = obj_build.make_admin_user(self.course) - self.do_patch_object_invalid_args_test( + response = self.do_patch_object_invalid_args_test( self.project, self.client, admin, self.url, request_data) + self.assertIn('closing_time', response.data) def test_non_admin_edit_project_permission_denied(self): staff = obj_build.make_staff_user(self.course)