Skip to content

Commit

Permalink
feat: delete allowance api
Browse files Browse the repository at this point in the history
  • Loading branch information
zacharis278 committed Jul 31, 2024
1 parent e4f2c9e commit 9aae411
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 2 deletions.
26 changes: 24 additions & 2 deletions edx_exams/apps/api/v1/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1789,16 +1789,18 @@ def setUp(self):
course_id=self.course_id,
)

def request_api(self, method, user, course_id, data=None):
def request_api(self, method, user, course_id, data=None, allowance_id=None):
"""
Helper function to make API request
"""
assert method in ['get', 'post']
assert method in ['get', 'post', 'delete']
headers = self.build_jwt_headers(user)
url = reverse(
'api:v1:course-allowances',
kwargs={'course_id': course_id}
)
if allowance_id:
url = f'{url}/{allowance_id}'

if data:
return getattr(self.client, method)(url, json.dumps(data), **headers, content_type='application/json')
Expand Down Expand Up @@ -1878,6 +1880,26 @@ def test_get_empty_response(self):
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, [])

def test_delete(self):
"""
Test that the endpoint deletes an allowance
"""
allowance = StudentAllowanceFactory.create(
exam=self.exam,
user=self.user,
)

response = self.request_api('delete', self.user, self.exam.course_id, allowance_id=allowance.id)
self.assertEqual(response.status_code, 204)
self.assertFalse(StudentAllowance.objects.filter(id=allowance.id).exists())

def test_delete_not_found(self):
"""
Test that 404 is returned if allowance does not exist
"""
response = self.request_api('delete', self.user, self.exam.course_id, allowance_id=19)
self.assertEqual(response.status_code, 404)

def test_post_allowances(self):
"""
Test that the endpoint creates allowances for the given request data
Expand Down
5 changes: 5 additions & 0 deletions edx_exams/apps/api/v1/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
app_name = 'v1'

urlpatterns = [
re_path(
fr'exams/course_id/{COURSE_ID_PATTERN}/allowances/(?P<allowance_id>\d+)',
AllowanceView.as_view(),
name='course-allowance'
),
re_path(
fr'exams/course_id/{COURSE_ID_PATTERN}/allowances',
AllowanceView.as_view(),
Expand Down
16 changes: 16 additions & 0 deletions edx_exams/apps/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,22 @@ def get(self, request, course_id):
allowances = StudentAllowance.get_allowances_for_course(course_id)
return Response(AllowanceSerializer(allowances, many=True).data)

def delete(self, request, course_id, allowance_id): # pylint: disable=unused-argument
"""
HTTP DELETE handler. Deletes all allowances for a course.
TODO: both this and the POST endpoint should be limiting operations by course_id
"""
try:
StudentAllowance.objects.get(id=allowance_id).delete()
except StudentAllowance.DoesNotExist:
return Response(
status=status.HTTP_404_NOT_FOUND,
data={'detail': f'Allowance with id={allowance_id} does not exist.'}
)

return Response(status=status.HTTP_204_NO_CONTENT)

def post(self, request, course_id): # pylint: disable=unused-argument
"""
HTTP POST handler. Creates allowances based on the given list.
Expand Down
2 changes: 2 additions & 0 deletions edx_exams/apps/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ class Status:
USAGE_KEY_PATTERN = r'(?P<content_id>(?:i4x://?[^/]+/[^/]+/[^/]+/[^@]+(?:@[^/]+)?)|(?:[^/]+))'

EXAM_ID_PATTERN = r'(?P<exam_id>\d+)'

ATTEMPT_ID_PATTERN = r'(?P<attempt_id>\d+)'

0 comments on commit 9aae411

Please sign in to comment.