Skip to content

Commit 7a8e256

Browse files
authored
Merge pull request #81 from AvaCodeSolutions/feat/77/get-course-content-api
feat: #77 API view to get a single course content
2 parents c28632c + 6f1cf47 commit 7a8e256

File tree

3 files changed

+61
-30
lines changed

3 files changed

+61
-30
lines changed

django_email_learning/api/views.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,23 @@ def get(self, request, *args, **kwargs) -> JsonResponse: # type: ignore[no-unty
9999
return JsonResponse({"error": "Course not found"}, status=404)
100100

101101

102+
@method_decorator(accessible_for(roles={"admin", "editor", "viewer"}), name="get")
102103
@method_decorator(accessible_for(roles={"admin", "editor"}), name="delete")
103104
class SingleCourseContentView(View):
105+
def get(self, request, *args, **kwargs) -> JsonResponse: # type: ignore[no-untyped-def]
106+
try:
107+
course_content = CourseContent.objects.get(id=kwargs["course_content_id"])
108+
return JsonResponse(
109+
serializers.CourseContentResponse.model_validate(
110+
course_content
111+
).model_dump(),
112+
status=200,
113+
)
114+
except CourseContent.DoesNotExist:
115+
return JsonResponse({"error": "Course content not found"}, status=404)
116+
except ValidationError as e:
117+
return JsonResponse({"error": e.errors()}, status=400)
118+
104119
def delete(self, request, *args, **kwargs): # type: ignore[no-untyped-def]
105120
try:
106121
course_content = CourseContent.objects.get(id=kwargs["course_content_id"])

tests/api/test_views/test_course_content_view.py

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@ def get_url() -> str:
1414
)
1515

1616

17+
def single_content_url(
18+
course_content_id: int, course_id: int, organization_id: int = 1
19+
) -> str:
20+
return reverse(
21+
"django_email_learning:api:single_course_content_view",
22+
kwargs={
23+
"organization_id": organization_id,
24+
"course_id": course_id,
25+
"course_content_id": course_content_id,
26+
},
27+
)
28+
29+
1730
def valid_create_course_payload(
1831
title: str = "Python Course",
1932
slug: str = "python",
@@ -389,37 +402,40 @@ def test_delete_course_content(superadmin_client, create_course):
389402
assert get_response.status_code == 404
390403

391404

392-
def test_viewer_cannot_delete_course_content(viewer_client, create_course):
393-
url = get_url()
394-
# Create a lesson content
395-
lesson_payload = {
396-
"content": {
397-
"title": LESSON_TITLE,
398-
"content": LESSON_CONTENT,
399-
"type": "lesson",
400-
},
401-
"priority": 1,
402-
"waiting_period": {"period": 2, "type": "days"},
403-
}
404-
response = viewer_client.post(
405-
url, json.dumps(lesson_payload), content_type="application/json"
405+
def test_viewer_cannot_delete_course_content(viewer_client, course_lesson_content):
406+
url = single_content_url(
407+
course_content_id=course_lesson_content.id,
408+
course_id=course_lesson_content.course.id,
409+
organization_id=course_lesson_content.course.organization.id,
406410
)
411+
response = viewer_client.delete(url)
407412
assert response.status_code == 403
408413

409414

410-
def test_anonymous_user_cannot_delete_course_content(anonymous_client, create_course):
411-
url = get_url()
412-
# Create a lesson content
413-
lesson_payload = {
414-
"content": {
415-
"title": LESSON_TITLE,
416-
"content": LESSON_CONTENT,
417-
"type": "lesson",
418-
},
419-
"priority": 1,
420-
"waiting_period": {"period": 2, "type": "days"},
421-
}
422-
response = anonymous_client.post(
423-
url, json.dumps(lesson_payload), content_type="application/json"
415+
def test_anonymous_user_cannot_delete_course_content(
416+
anonymous_client, course_lesson_content
417+
):
418+
url = single_content_url(
419+
course_content_id=course_lesson_content.id,
420+
course_id=course_lesson_content.course.id,
421+
organization_id=course_lesson_content.course.organization.id,
424422
)
423+
response = anonymous_client.delete(url)
425424
assert response.status_code == 401
425+
426+
427+
def test_get_course_content(viewer_client, course_lesson_content):
428+
url = single_content_url(
429+
course_content_id=course_lesson_content.id,
430+
course_id=course_lesson_content.course.id,
431+
organization_id=course_lesson_content.course.organization.id,
432+
)
433+
get_response = viewer_client.get(url)
434+
assert get_response.status_code == 200
435+
get_data = get_response.json()
436+
assert get_data["id"] == course_lesson_content.id
437+
assert get_data["type"] == "lesson"
438+
assert get_data["priority"] == 1
439+
assert get_data["waiting_period"] == {"period": 1, "type": "hours"}
440+
assert get_data["lesson"]["title"] == course_lesson_content.lesson.title
441+
assert get_data["lesson"]["content"] == course_lesson_content.lesson.content

tests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,14 +165,14 @@ def enrollment(db, learner, course) -> Enrollment:
165165
@pytest.fixture
166166
def course_lesson_content(db, course, lesson) -> CourseContent:
167167
content = CourseContent.objects.create(
168-
course=course, priority=1, type="lesson", lesson=lesson, waiting_period=10
168+
course=course, priority=1, type="lesson", lesson=lesson, waiting_period=3600
169169
)
170170
return content
171171

172172

173173
@pytest.fixture
174174
def course_quiz_content(db, course, quiz) -> CourseContent:
175175
content = CourseContent.objects.create(
176-
course=course, priority=2, type="quiz", quiz=quiz, waiting_period=5
176+
course=course, priority=2, type="quiz", quiz=quiz, waiting_period=3600
177177
)
178178
return content

0 commit comments

Comments
 (0)