From c08540fd73c7281441b49c2c3c87424e56361f85 Mon Sep 17 00:00:00 2001 From: Vincent Vallaeys Date: Mon, 13 May 2024 14:39:56 +0200 Subject: [PATCH] chore: readded tests (#419) --- backend/api/logic/parse_zip_files.py | 12 +- backend/api/models/course.py | 2 + backend/api/tests/helpers.py | 49 +- backend/api/tests/test_admin.py | 19 +- backend/api/tests/test_assistant.py | 30 +- backend/api/tests/test_checks.py | 222 ++++---- backend/api/tests/test_course.py | 53 +- backend/api/tests/test_file_structure.py | 152 +++--- backend/api/tests/test_group.py | 29 +- backend/api/tests/test_locale.py | 12 +- backend/api/tests/test_project.py | 472 +++++++++--------- backend/api/tests/test_student.py | 26 +- backend/api/tests/test_submission.py | 443 +++++++--------- backend/api/tests/test_teacher.py | 23 +- .../testing/docker_images/Dockerfile.python | 1 + test.yml | 2 +- 16 files changed, 756 insertions(+), 791 deletions(-) create mode 100644 backend/data/testing/docker_images/Dockerfile.python diff --git a/backend/api/logic/parse_zip_files.py b/backend/api/logic/parse_zip_files.py index 0240c48a..7858a585 100644 --- a/backend/api/logic/parse_zip_files.py +++ b/backend/api/logic/parse_zip_files.py @@ -1,3 +1,4 @@ +import os import zipfile from api.models.checks import FileExtension, StructureCheck @@ -13,7 +14,16 @@ def parse_zip(project: Project, zip_file: InMemoryUploadedFile) -> bool: with zipfile.ZipFile(zip_file, 'r') as zip: files = zip.namelist() - directories = [file.filename for file in zip.infolist() if file.is_dir()] + directories = [file for file in files if file.endswith('/')] + + # Check if all directories start the same + common_prefix = os.path.commonprefix(directories) + if '/' in common_prefix: + prefixes = common_prefix.split('/') + if common_prefix[-1] != '/': + prefixes = prefixes[:-1] + + directories += [prefix + '/' for prefix in prefixes] # Add for each directory a structure check for directory in directories: diff --git a/backend/api/models/course.py b/backend/api/models/course.py index 7d4b766c..c8f4d27f 100644 --- a/backend/api/models/course.py +++ b/backend/api/models/course.py @@ -8,6 +8,7 @@ if TYPE_CHECKING: from api.models.assistant import Assistant + from api.models.project import Project from api.models.student import Student from api.models.teacher import Teacher from django.db.models.manager import RelatedManager @@ -95,5 +96,6 @@ def academic_year(self) -> str: if TYPE_CHECKING: assistants: RelatedManager['Assistant'] + projects: RelatedManager['Project'] students: RelatedManager['Student'] teachers: RelatedManager['Teacher'] diff --git a/backend/api/tests/helpers.py b/backend/api/tests/helpers.py index 9f5dfe8b..20df3b84 100644 --- a/backend/api/tests/helpers.py +++ b/backend/api/tests/helpers.py @@ -1,6 +1,9 @@ +from datetime import timedelta + from api.models.assistant import Assistant -from api.models.checks import FileExtension, StructureCheck +from api.models.checks import ExtraCheck, FileExtension, StructureCheck from api.models.course import Course +from api.models.docker import DockerImage from api.models.group import Group from api.models.project import Project from api.models.student import Student @@ -15,7 +18,7 @@ def create_faculty(name: str | int) -> Faculty: return Faculty.objects.create(id=name, name=name) -def create_user(id: str | int, first_name: str, last_name: str, email: str, faculty: list[Faculty] = None) -> User: +def create_user(id: str | int, first_name: str, last_name: str, email: str, faculties: list[Faculty] | None = None) -> User: username = f"{first_name.lower()}{last_name.lower()}" user = User.objects.create( @@ -26,14 +29,14 @@ def create_user(id: str | int, first_name: str, last_name: str, email: str, facu email=email ) - if faculty is not None: - for faculty in faculty: + if faculties is not None: + for faculty in faculties: user.faculties.add(faculty) return user -def create_admin(id: str | int, first_name: str, last_name: str, email: str, faculty: list[Faculty] = None): +def create_admin(id: str | int, first_name: str, last_name: str, email: str, faculty: list[Faculty] | None = None): """Create an Admin with the given arguments.""" admin = create_user(id, first_name, last_name, email, faculty) admin.make_admin() @@ -47,8 +50,8 @@ def create_student( email: str, student_id: str = "", is_active: bool = True, - faculty: list[Faculty] = None, - courses: list[Course] = None + faculty: list[Faculty] | None = None, + courses: list[Course] | None = None ) -> Student: """Create a student with the given arguments.""" username = f"{first_name.lower()}{last_name.lower()}" @@ -143,6 +146,11 @@ def create_structure_check(path, project, obligated_extensions, blocked_extensio return check +def create_extra_check(project, docker_image, file): + """Create an ExtraCheck with the given arguments.""" + return ExtraCheck.objects.create(name="test extra check", project=project, docker_image=docker_image, file=file) + + def create_project(name, description, days, course, max_score=5, group_size=5, visible=True, archived=False): """Create a Project with the given arguments.""" deadline = timezone.now() + timezone.timedelta(days=days) @@ -159,7 +167,12 @@ def create_project(name, description, days, course, max_score=5, group_size=5, v ) -def create_course(name: str | int, academic_startyear: int, description: str = None, parent_course: Course = None) -> Course: +def create_course( + name: str | int, + academic_startyear: int, + description: str | None = None, + parent_course: Course | None = None +) -> Course: """Create a Course with the given arguments.""" return Course.objects.create( name=name, @@ -174,11 +187,25 @@ def create_group(project: Project, score: int = 0) -> Group: return Group.objects.create(project=project, score=score) -def create_submission(submission_number: int, group: Group, structure_checks_passed: bool) -> Submission: +def create_submission(group: Group, zip: str) -> Submission: """Create a Submission with the given arguments.""" return Submission.objects.create( - submission_number=submission_number, group=group, - structure_checks_passed=structure_checks_passed, + zip=zip, + ) + + +def create_docker_image(file: str, owner: User): + """Create a DockerImage with the given arguments.""" + return DockerImage.objects.create(name="test docker image", owner=owner, file=file) + + +def create_past_project(name, description, days, course, days_start_date): + """Create a Project with the given arguments.""" + deadline = timezone.now() + timedelta(days=days) + start_date = timezone.now() + timedelta(days=days_start_date) + + return Project.objects.create( + name=name, description=description, deadline=deadline, course=course, score_visible=True, start_date=start_date ) diff --git a/backend/api/tests/test_admin.py b/backend/api/tests/test_admin.py index d9eb73a6..60801867 100644 --- a/backend/api/tests/test_admin.py +++ b/backend/api/tests/test_admin.py @@ -1,13 +1,14 @@ import json -from django.urls import reverse -from rest_framework.test import APITestCase + from api.tests.helpers import create_admin, create_faculty from authentication.models import User +from django.urls import reverse +from rest_framework.test import APITestCase class AdminModelTests(APITestCase): def setUp(self): - self.client.force_authenticate( + self.client.force_authenticate( # type: ignore User.get_dummy_admin() ) @@ -19,7 +20,7 @@ def test_no_admins(self): response_root = self.client.get(reverse("admin-list"), follow=True) self.assertEqual(response_root.status_code, 200) # Assert that the response is JSON - self.assertEqual(response_root.accepted_media_type, "application/json") + self.assertEqual(response_root.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response_root.content.decode("utf-8")) # Assert that the parsed JSON is an empty list @@ -40,7 +41,7 @@ def test_admin_exists(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -75,7 +76,7 @@ def test_multiple_admins(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -113,7 +114,7 @@ def test_admin_detail_view(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -147,7 +148,7 @@ def test_admin_faculty(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -164,7 +165,7 @@ def test_admin_faculty(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) diff --git a/backend/api/tests/test_assistant.py b/backend/api/tests/test_assistant.py index 04957bff..1d0b7474 100644 --- a/backend/api/tests/test_assistant.py +++ b/backend/api/tests/test_assistant.py @@ -1,15 +1,17 @@ import json -from django.urls import reverse -from rest_framework.test import APITestCase + from api.models.assistant import Assistant from api.models.teacher import Teacher -from api.tests.helpers import create_faculty, create_course, create_assistant, create_user +from api.tests.helpers import (create_assistant, create_course, create_faculty, + create_user) from authentication.models import User +from django.urls import reverse +from rest_framework.test import APITestCase class AssistantModelTests(APITestCase): def setUp(self) -> None: - self.client.force_authenticate( + self.client.force_authenticate( # type: ignore User.get_dummy_admin() ) @@ -75,7 +77,7 @@ def test_no_assistant(self): response_root = self.client.get(reverse("assistant-list"), follow=True) self.assertEqual(response_root.status_code, 200) # Assert that the response is JSON - self.assertEqual(response_root.accepted_media_type, "application/json") + self.assertEqual(response_root.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response_root.content.decode("utf-8")) # Assert that the parsed JSON is an empty list @@ -96,7 +98,7 @@ def test_assistant_exists(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -131,7 +133,7 @@ def test_multiple_assistant(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -170,7 +172,7 @@ def test_assistant_detail_view(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -205,7 +207,7 @@ def test_assistant_faculty(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -223,7 +225,7 @@ def test_assistant_faculty(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -262,7 +264,7 @@ def test_assistant_courses(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -280,7 +282,7 @@ def test_assistant_courses(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -311,7 +313,7 @@ def setUp(self) -> None: email="John.Doe@gmail.com" ) - self.client.force_authenticate(self.user) + self.client.force_authenticate(self.user) # type: ignore def test_retrieve_assistant_list(self): """ @@ -333,7 +335,7 @@ def test_retrieve_assistant_list(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) diff --git a/backend/api/tests/test_checks.py b/backend/api/tests/test_checks.py index a38f3016..6ea237a1 100644 --- a/backend/api/tests/test_checks.py +++ b/backend/api/tests/test_checks.py @@ -1,10 +1,13 @@ import json -from api.tests.helpers import (create_course, create_file_extension, - create_project, create_structure_check) +from api.tests.helpers import (create_admin, create_course, + create_docker_image, create_extra_check, + create_file_extension, create_project, + create_structure_check) from authentication.models import User from django.urls import reverse from rest_framework.test import APITestCase +from ypovoli.settings import TESTING_BASE_LINK def get_project(): @@ -25,7 +28,7 @@ def get_project(): class FileExtensionModelTests(APITestCase): def setUp(self) -> None: - self.client.force_authenticate( + self.client.force_authenticate( # type: ignore User.get_dummy_admin() ) @@ -36,7 +39,7 @@ def test_no_file_extension(self): response_root = self.client.get(reverse("file-extension-list"), follow=True) self.assertEqual(response_root.status_code, 200) # Assert that the response is JSON - self.assertEqual(response_root.accepted_media_type, "application/json") + self.assertEqual(response_root.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response_root.content.decode("utf-8")) # Assert that the parsed JSON is an empty list @@ -55,7 +58,7 @@ def test_file_extension_exists(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -83,7 +86,7 @@ def test_multiple_file_extension(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -118,7 +121,7 @@ def test_file_extension_detail_view(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -128,119 +131,92 @@ def test_file_extension_detail_view(self): self.assertEqual(content_json["extension"], file_extension.extension) -# class StructureCheckModelTests(APITestCase): -# def setUp(self) -> None: -# self.client.force_authenticate( -# User.get_dummy_admin() -# ) - -# def test_no_checks(self): -# """ -# Able to retrieve no Checks before publishing it. -# """ -# response_root = self.client.get(reverse("structure-check-list"), follow=True) -# self.assertEqual(response_root.status_code, 200) -# self.assertEqual(response_root.accepted_media_type, "application/json") -# content_json = json.loads(response_root.content.decode("utf-8")) -# self.assertEqual(content_json, []) - -# def test_structure_checks_exists(self): -# """ -# Able to retrieve a single Checks after creating it. -# """ -# # Create a Checks instance with some file extensions -# file_extension1 = create_file_extension(extension="jpg") -# file_extension2 = create_file_extension(extension="png") -# file_extension3 = create_file_extension(extension="tar") -# file_extension4 = create_file_extension(extension="wfp") -# checks = create_structure_check( -# path=".", -# project=get_project(), -# obligated_extensions=[file_extension1, file_extension4], -# blocked_extensions=[file_extension2, file_extension3], -# ) - -# # Make a GET request to retrieve the Checks -# response = self.client.get(reverse("structure-check-list"), follow=True) - -# # Check if the response was successful -# self.assertEqual(response.status_code, 200) -# self.assertEqual(response.accepted_media_type, "application/json") - -# # Parse the JSON content from the response -# content_json = json.loads(response.content.decode("utf-8")) - -# # Assert that the parsed JSON is a list with one Checks -# self.assertEqual(len(content_json), 1) - -# # Assert the details of the retrieved Checks match the created Checks -# retrieved_checks = content_json[0] -# self.assertEqual(int(retrieved_checks["id"]), checks.id) - -# # Assert the file extensions of the retrieved -# # Checks match the created file extensions -# retrieved_obligated_file_extensions = retrieved_checks["obligated_extensions"] - -# self.assertEqual(len(retrieved_obligated_file_extensions), 2) -# self.assertEqual( -# retrieved_obligated_file_extensions[0]["extension"], file_extension1.extension -# ) -# self.assertEqual( -# retrieved_obligated_file_extensions[1]["extension"], file_extension4.extension -# ) - -# retrieved_blocked_file_extensions = retrieved_checks[ -# "blocked_extensions" -# ] -# self.assertEqual(len(retrieved_blocked_file_extensions), 2) -# self.assertEqual( -# retrieved_blocked_file_extensions[0]["extension"], -# file_extension2.extension, -# ) -# self.assertEqual( -# retrieved_blocked_file_extensions[1]["extension"], -# file_extension3.extension, -# ) - - -# class ExtraCheckModelTests(APITestCase): -# def setUp(self) -> None: -# self.client.force_authenticate( -# User.get_dummy_admin() -# ) - -# def test_no_checks(self): -# """ -# Able to retrieve no Checks before publishing it. -# """ -# response_root = self.client.get(reverse("extra-check-list"), follow=True) -# self.assertEqual(response_root.status_code, 200) -# self.assertEqual(response_root.accepted_media_type, "application/json") -# content_json = json.loads(response_root.content.decode("utf-8")) -# self.assertEqual(content_json, []) - -# def test_extra_checks_exists(self): -# """ -# Able to retrieve a single Checks after creating it. -# """ -# checks = create_extra_check( -# project=get_project(), run_script="test.sh" -# ) - -# # Make a GET request to retrieve the Checks -# response = self.client.get(reverse("extra-check-list"), follow=True) - -# # Check if the response was successful -# self.assertEqual(response.status_code, 200) -# self.assertEqual(response.accepted_media_type, "application/json") - -# # Parse the JSON content from the response -# content_json = json.loads(response.content.decode("utf-8")) - -# # Assert that the parsed JSON is a list with one Checks -# self.assertEqual(len(content_json), 1) - -# # Assert the details of the retrieved Checks match the created Checks -# retrieved_checks = content_json[0] -# self.assertEqual(int(retrieved_checks["id"]), checks.id) -# self.assertEqual(retrieved_checks["run_script"], settings.TESTING_BASE_LINK + checks.run_script.url) +class StructureCheckModelTests(APITestCase): + def setUp(self) -> None: + self.client.force_authenticate( # type: ignore + User.get_dummy_admin() + ) + + def test_structure_checks_exists(self): + """ + Able to retrieve a single check after creating it. + """ + # Create a Checks instance with some file extensions + file_extension1 = create_file_extension(extension="jpg") + file_extension2 = create_file_extension(extension="png") + file_extension3 = create_file_extension(extension="tar") + file_extension4 = create_file_extension(extension="wfp") + check = create_structure_check( + path="", + project=get_project(), + obligated_extensions=[file_extension1, file_extension4], + blocked_extensions=[file_extension2, file_extension3], + ) + + # Make a GET request to retrieve the Checks + response = self.client.get(reverse("structure-check-detail", args=[str(check.id)]), follow=True) + + # Check if the response was successful + self.assertEqual(response.status_code, 200) + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore + + # Parse the JSON content from the response + content_json = json.loads(response.content.decode("utf-8")) + + # Assert the details of the retrieved Checks match the created Checks + self.assertEqual(int(content_json["id"]), check.id) + + # Assert the file extensions of the retrieved + # Checks match the created file extensions + retrieved_obligated_file_extensions = content_json["obligated_extensions"] + + self.assertEqual(len(retrieved_obligated_file_extensions), 2) + self.assertEqual( + retrieved_obligated_file_extensions[0]["extension"], file_extension1.extension + ) + self.assertEqual( + retrieved_obligated_file_extensions[1]["extension"], file_extension4.extension + ) + + retrieved_blocked_file_extensions = content_json[ + "blocked_extensions" + ] + self.assertEqual(len(retrieved_blocked_file_extensions), 2) + self.assertEqual( + retrieved_blocked_file_extensions[0]["extension"], + file_extension2.extension, + ) + self.assertEqual( + retrieved_blocked_file_extensions[1]["extension"], + file_extension3.extension, + ) + + +class ExtraCheckModelTests(APITestCase): + def setUp(self) -> None: + self.client.force_authenticate( # type: ignore + User.get_dummy_admin() + ) + + def test_extra_checks_exists(self): + """ + Able to retrieve a single check after creating it. + """ + admin = create_admin(50, "John", "Doe", "John@Doe.com", []) + check = create_extra_check( + project=get_project(), docker_image=create_docker_image("", admin), file="test.sh" + ) + + # Make a GET request to retrieve the Checks + response = self.client.get(reverse("extra-check-detail", args=[str(check.id)]), follow=True) + + # Check if the response was successful + self.assertEqual(response.status_code, 200) + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore + + # Parse the JSON content from the response + content_json = json.loads(response.content.decode("utf-8")) + + # Assert the details of the retrieved Checks match the created Checks + self.assertEqual(int(content_json["id"]), check.id) + self.assertEqual(content_json["file"], TESTING_BASE_LINK + check.file.url) diff --git a/backend/api/tests/test_course.py b/backend/api/tests/test_course.py index 55b43661..038481d1 100644 --- a/backend/api/tests/test_course.py +++ b/backend/api/tests/test_course.py @@ -1,18 +1,16 @@ import json -from django.utils import timezone -from django.urls import reverse -from rest_framework.test import APITestCase -from authentication.models import User +from typing import cast + from api.models.course import Course -from api.models.teacher import Teacher from api.models.student import Student -from api.tests.helpers import (create_course, - create_assistant, - create_student, - create_teacher, - create_project, - create_faculty) +from api.models.teacher import Teacher +from api.tests.helpers import (create_assistant, create_course, create_faculty, + create_project, create_student, create_teacher) +from authentication.models import Faculty, User from django.core.files.uploadedfile import SimpleUploadedFile +from django.urls import reverse +from django.utils import timezone +from rest_framework.test import APITestCase def get_course(): @@ -47,7 +45,7 @@ def get_student(): class CourseModelTests(APITestCase): def setUp(self) -> None: - self.client.force_authenticate( + self.client.force_authenticate( # type: ignore User.get_dummy_admin() ) @@ -57,7 +55,7 @@ def test_no_courses(self): """ response_root = self.client.get(reverse("course-list"), follow=True) self.assertEqual(response_root.status_code, 200) - self.assertEqual(response_root.accepted_media_type, "application/json") + self.assertEqual(response_root.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response_root.content.decode("utf-8")) self.assertEqual(content_json, []) @@ -74,7 +72,7 @@ def test_course_exists(self): response = self.client.get(reverse("course-list"), follow=True) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -105,7 +103,7 @@ def test_multiple_courses(self): response = self.client.get(reverse("course-list"), follow=True) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -139,7 +137,7 @@ def test_course_detail_view(self): ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -175,7 +173,7 @@ def test_course_teachers(self): ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -189,7 +187,7 @@ def test_course_teachers(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -237,7 +235,7 @@ def test_course_assistant(self): ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -251,7 +249,7 @@ def test_course_assistant(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -300,7 +298,7 @@ def test_course_student(self): ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -314,7 +312,7 @@ def test_course_student(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -371,7 +369,7 @@ def test_course_project(self): ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -385,7 +383,7 @@ def test_course_project(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -418,7 +416,7 @@ def setUp(self) -> None: email="Bobke.Peeters@gmail.com" ) - self.client.force_authenticate( + self.client.force_authenticate( # type: ignore self.user ) @@ -659,7 +657,7 @@ def setUp(self) -> None: email="Bobke.Peeters@gmail.com" ) - self.client.force_authenticate( + self.client.force_authenticate( # type: ignore self.user ) @@ -798,7 +796,8 @@ def test_create_course(self): self.assertTrue(course.teachers.filter(id=self.user.id).exists()) # Make sure the course is linked to the faculty - self.assertEqual(course.faculty.id, faculty.id) + faculty: Faculty = cast(Faculty, course.faculty) + self.assertEqual(faculty.id, faculty.id) def test_create_project(self): """ diff --git a/backend/api/tests/test_file_structure.py b/backend/api/tests/test_file_structure.py index c75f089f..7b947301 100644 --- a/backend/api/tests/test_file_structure.py +++ b/backend/api/tests/test_file_structure.py @@ -1,17 +1,18 @@ import json import os -from api.tests.helpers import (create_course, create_file_extension, - create_project, create_structure_check) +from api.logic.parse_zip_files import parse_zip +from api.tests.helpers import create_course, create_project from authentication.models import User from django.conf import settings +from django.core.files.uploadedfile import SimpleUploadedFile from django.urls import reverse from rest_framework.test import APITestCase class FileTestsTests(APITestCase): def setUp(self): - self.client.force_authenticate( + self.client.force_authenticate( # type: ignore User.get_dummy_admin() ) # Set up a temporary directory for MEDIA_ROOT during tests @@ -22,84 +23,73 @@ def tearDown(self): # Restore the original MEDIA_ROOT after tests settings.MEDIA_ROOT = self.old_media_root - # def test_parsing(self): - # course = create_course(name="test course", academic_startyear=2024) - # project = create_project( - # group_size=5, - # max_score=10, - # name="test", - # description="descr", - # visible=True, - # archived=False, - # days=100, - # course=course, - # ) - # parse_zip_file(project=project, dir_path="structures/zip_struct1.zip") - - # response = self.client.get( - # reverse("project-detail", args=[str(project.id)]), follow=True - # ) - # self.assertEqual(response.status_code, 200) - # self.assertEqual(response.accepted_media_type, "application/json") + def test_parsing(self): + course = create_course(name="test course", academic_startyear=2024) + project = create_project( + group_size=5, + max_score=10, + name="test", + description="descr", + visible=True, + archived=False, + days=100, + course=course, + ) - # content_json = json.loads(response.content.decode("utf-8")) + memory_file = SimpleUploadedFile("zip_struct1.zip", open( + f"{settings.MEDIA_ROOT}/structures/zip_struct1.zip", "rb").read(), content_type='application/zip') - # response = self.client.get( - # content_json["structure_checks"], follow=True - # ) + parse_zip(project=project, zip_file=memory_file) - # self.assertEqual(response.status_code, 200) - # self.assertEqual(response.accepted_media_type, "application/json") + response = self.client.get( + reverse("project-structure-checks", args=[str(project.id)]), follow=True + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore - # content_json = json.loads(response.content.decode("utf-8")) + content_json = json.loads(response.content.decode("utf-8")) - # self.assertEqual(len(content_json), 7) + self.assertEqual(len(content_json), 6) - # expected_project_url = settings.TESTING_BASE_LINK + reverse( - # "project-detail", args=[str(project.id)] - # ) + expected_project_url = settings.TESTING_BASE_LINK + reverse( + "project-detail", args=[str(project.id)] + ) - # content = content_json[0] - # self.assertEqual(content["path"], ".") - # self.assertEqual(content["project"], expected_project_url) - # self.assertEqual(len(content["obligated_extensions"]), 0) - # self.assertEqual(len(content["blocked_extensions"]), 0) - - # content = content_json[1] - # self.assertEqual(content["path"], "folder_struct1") - # self.assertEqual(content["project"], expected_project_url) - # self.assertEqual(len(content["obligated_extensions"]), 1) - # self.assertEqual(len(content["blocked_extensions"]), 0) - - # content = content_json[2] - # self.assertEqual(content["path"], "folder_struct1/submap1") - # self.assertEqual(content["project"], expected_project_url) - # self.assertEqual(len(content["obligated_extensions"]), 2) - # self.assertEqual(len(content["blocked_extensions"]), 0) - - # content = content_json[3] - # self.assertEqual(content["path"], "folder_struct1/submap1/templates") - # self.assertEqual(content["project"], expected_project_url) - # self.assertEqual(len(content["obligated_extensions"]), 1) - # self.assertEqual(len(content["blocked_extensions"]), 0) - - # content = content_json[4] - # self.assertEqual(content["path"], "folder_struct1/submap2") - # self.assertEqual(content["project"], expected_project_url) - # self.assertEqual(len(content["obligated_extensions"]), 1) - # self.assertEqual(len(content["blocked_extensions"]), 0) - - # content = content_json[5] - # self.assertEqual(content["path"], "folder_struct1/submap2/src") - # self.assertEqual(content["project"], expected_project_url) - # self.assertEqual(len(content["obligated_extensions"]), 3) - # self.assertEqual(len(content["blocked_extensions"]), 0) - - # content = content_json[6] - # self.assertEqual(content["path"], "folder_struct1/submap3") - # self.assertEqual(content["project"], expected_project_url) - # self.assertEqual(len(content["obligated_extensions"]), 2) - # self.assertEqual(len(content["blocked_extensions"]), 0) + content = content_json[0] + self.assertEqual(content["path"], "folder_struct1/submap1/") + self.assertEqual(content["project"], expected_project_url) + self.assertEqual(len(content["obligated_extensions"]), 2) + self.assertEqual(len(content["blocked_extensions"]), 0) + + content = content_json[1] + self.assertEqual(content["path"], "folder_struct1/submap1/templates/") + self.assertEqual(content["project"], expected_project_url) + self.assertEqual(len(content["obligated_extensions"]), 1) + self.assertEqual(len(content["blocked_extensions"]), 0) + + content = content_json[2] + self.assertEqual(content["path"], "folder_struct1/submap2/") + self.assertEqual(content["project"], expected_project_url) + self.assertEqual(len(content["obligated_extensions"]), 1) + self.assertEqual(len(content["blocked_extensions"]), 0) + + content = content_json[3] + self.assertEqual(content["path"], "folder_struct1/submap2/src/") + self.assertEqual(content["project"], expected_project_url) + self.assertEqual(len(content["obligated_extensions"]), 3) + self.assertEqual(len(content["blocked_extensions"]), 0) + + content = content_json[4] + self.assertEqual(content["path"], "folder_struct1/submap3/") + self.assertEqual(content["project"], expected_project_url) + self.assertEqual(len(content["obligated_extensions"]), 2) + self.assertEqual(len(content["blocked_extensions"]), 0) + + content = content_json[5] + self.assertEqual(content["path"], "folder_struct1/") + self.assertEqual(content["project"], expected_project_url) + self.assertEqual(len(content["obligated_extensions"]), 1) + self.assertEqual(len(content["blocked_extensions"]), 0) # def test_checking(self): # course = create_course(name="test course", academic_startyear=2024) @@ -126,43 +116,43 @@ def tearDown(self): # fileExtensionTSX = create_file_extension(extension="tsx") # create_structure_check( - # path=".", + # path="", # project=project, # obligated_extensions=[], # blocked_extensions=[]) # create_structure_check( - # path="folder_struct1", + # path="folder_struct1/", # project=project, # obligated_extensions=[fileExtensionHS], # blocked_extensions=[]) # create_structure_check( - # path="folder_struct1/submap1", + # path="folder_struct1/submap1/", # project=project, # obligated_extensions=[fileExtensionPDF, fileExtensionDOCX], # blocked_extensions=[]) # create_structure_check( - # path="folder_struct1/submap1/templates", + # path="folder_struct1/submap1/templates/", # project=project, # obligated_extensions=[fileExtensionLATEX], # blocked_extensions=[]) # create_structure_check( - # path="folder_struct1/submap2", + # path="folder_struct1/submap2/", # project=project, # obligated_extensions=[fileExtensionMD], # blocked_extensions=[]) # create_structure_check( - # path="folder_struct1/submap2/src", + # path="folder_struct1/submap2/src/", # project=project, # obligated_extensions=[fileExtensionPY, fileExtensionHPP, fileExtensionCPP], # blocked_extensions=[]) # create_structure_check( - # path="folder_struct1/submap3", + # path="folder_struct1/submap3/", # project=project, # obligated_extensions=[fileExtensionTS, fileExtensionTSX], # blocked_extensions=[]) diff --git a/backend/api/tests/test_group.py b/backend/api/tests/test_group.py index 07c56940..a3fb21bd 100644 --- a/backend/api/tests/test_group.py +++ b/backend/api/tests/test_group.py @@ -1,16 +1,17 @@ import json -from django.urls import reverse -from django.conf import settings -from rest_framework.test import APITestCase + from api.models.student import Student from api.models.teacher import Teacher -from api.tests.helpers import create_course, create_project, create_student, create_group +from api.tests.helpers import (create_course, create_group, create_project, + create_student) from authentication.models import User +from django.urls import reverse +from rest_framework.test import APITestCase class GroupModelTests(APITestCase): def setUp(self) -> None: - self.client.force_authenticate( + self.client.force_authenticate( # type: ignore User.get_dummy_admin() ) @@ -33,7 +34,7 @@ def test_group_detail_view(self): reverse("group-detail", args=[str(group.id)]), follow=True ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -59,7 +60,7 @@ def test_group_project(self): reverse("group-detail", args=[str(group.id)]), follow=True ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -98,7 +99,7 @@ def test_group_students(self): reverse("group-detail", args=[str(group.id)]), follow=True ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -111,7 +112,7 @@ def test_group_students(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -140,7 +141,7 @@ def setUp(self) -> None: email="Test@gmail.com" ) - self.client.force_authenticate( + self.client.force_authenticate( # type: ignore self.user ) @@ -168,7 +169,7 @@ def test_assign_student_to_group(self): ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Make sure the student is in the group now self.assertTrue(group.students.filter(id=student.id).exists()) @@ -197,7 +198,7 @@ def test_remove_student_from_group(self): ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Make sure the student is not in the group anymore self.assertFalse(group.students.filter(id=student.id).exists()) @@ -222,7 +223,7 @@ def test_update_score_of_group(self): ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Make sure the score of the group is updated group.refresh_from_db() @@ -252,7 +253,7 @@ def setUp(self) -> None: email="Bobke.Peeters@gmail.com" ) - self.client.force_authenticate( + self.client.force_authenticate( # type: ignore self.user ) diff --git a/backend/api/tests/test_locale.py b/backend/api/tests/test_locale.py index 13a53844..a31aa718 100644 --- a/backend/api/tests/test_locale.py +++ b/backend/api/tests/test_locale.py @@ -1,17 +1,17 @@ import json -from django.urls import reverse -from django.utils.translation import activate -from django.utils.translation import gettext as _ -from rest_framework.test import APITestCase from api.models.course import Course from api.models.student import Student from authentication.models import User +from django.urls import reverse +from django.utils.translation import activate +from django.utils.translation import gettext as _ +from rest_framework.test import APITestCase class TestLocaleAddAlreadyPresentStudentToCourse(APITestCase): def setUp(self) -> None: - self.client.force_authenticate(User.get_dummy_admin()) + self.client.force_authenticate(User.get_dummy_admin()) # type: ignore course = Course.objects.create(id=1, name="Test Course", academic_startyear=2024) student = Student.objects.create(id=1, first_name="John", last_name="Doe", email="john.doe@example.com") @@ -30,7 +30,7 @@ def test_default_locale(self): def test_nl_locale(self): response = self.client.post(reverse("course-students", args=["1"]), {"student": 1}, - headers={"accept-language": "nl"}) + headers={"accept-language": "nl"}) # type: ignore self.assertEqual(response.status_code, 400) body = json.loads(response.content.decode('utf-8')) diff --git a/backend/api/tests/test_project.py b/backend/api/tests/test_project.py index 52a8506c..98047703 100644 --- a/backend/api/tests/test_project.py +++ b/backend/api/tests/test_project.py @@ -1,13 +1,14 @@ import json from api.models.checks import ExtraCheck, StructureCheck +from api.models.docker import DockerImage from api.models.project import Project from api.models.student import Student from api.models.teacher import Teacher -from api.tests.helpers import (create_course, create_file_extension, - create_group, create_project, - create_structure_check, create_student, - create_submission) +from api.tests.helpers import (create_admin, create_course, + create_file_extension, create_group, + create_project, create_structure_check, + create_student, create_submission) from authentication.models import User from django.conf import settings from django.urls import reverse @@ -18,7 +19,7 @@ class ProjectModelTests(APITestCase): def setUp(self) -> None: - self.client.force_authenticate(User.get_dummy_admin()) + self.client.force_authenticate(User.get_dummy_admin()) # type: ignore def test_toggle_visible(self): """ @@ -273,7 +274,7 @@ def test_project_exists(self): ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -305,7 +306,7 @@ def test_project_course(self): ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -349,7 +350,7 @@ def test_project_structure_checks(self): ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -367,7 +368,7 @@ def test_project_structure_checks(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8"))[0] @@ -428,7 +429,7 @@ def test_project_structure_checks_post(self): project.refresh_from_db() self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # self.assertEqual(json.loads(response.content), {'message': gettext('project.success.structure_check.add')}) upd: StructureCheck = project.structure_checks.all()[0] @@ -489,7 +490,7 @@ def test_project_structure_checks_post_already_existing(self): ) self.assertEqual(response.status_code, 400) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore self.assertEqual(json.loads(response.content), { 'non_field_errors': [gettext("project.error.structure_checks.already_existing")]}) @@ -523,60 +524,62 @@ def test_project_structure_checks_post_blocked_and_obligated(self): ) self.assertEqual(response.status_code, 400) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore self.assertEqual(json.loads(response.content), { 'non_field_errors': [gettext("project.error.structure_checks.extension_blocked_and_obligated")]}) - # def test_project_extra_checks(self): - # """ - # Able to retrieve an extra check of a project after creating it. - # """ - # course = create_course(id=3, name="test course", academic_startyear=2024) - # project = create_project( - # name="test project", - # description="test description", - # visible=True, - # archived=False, - # days=7, - # course=course, - # ) - # checks = ExtraCheck.objects.create( - # id=5, - # project=project, - # run_script="testscript.sh", - # ) - - # response = self.client.get( - # reverse("project-detail", args=[str(project.id)]), follow=True - # ) - - # self.assertEqual(response.status_code, 200) - # self.assertEqual(response.accepted_media_type, "application/json") - - # content_json = json.loads(response.content.decode("utf-8")) - - # retrieved_project = content_json - - # response = self.client.get(retrieved_project["extra_checks"], follow=True) - - # # Check if the response was successful - # self.assertEqual(response.status_code, 200) - - # # Assert that the response is JSON - # self.assertEqual(response.accepted_media_type, "application/json") - - # # Parse the JSON content from the response - # content_json = json.loads(response.content.decode("utf-8"))[0] - - # self.assertEqual(int(content_json["id"]), checks.id) - # self.assertEqual( - # content_json["project"], - # settings.TESTING_BASE_LINK + reverse("project-detail", args=[str(project.id)]), - # ) - # self.assertEqual( - # content_json["run_script"], - # settings.TESTING_BASE_LINK + checks.run_script.url, - # ) + def test_project_extra_checks(self): + """ + Able to retrieve an extra check of a project after creating it. + """ + course = create_course(name="test course", academic_startyear=2024) + project = create_project( + name="test project", + description="test description", + visible=True, + archived=False, + days=7, + course=course, + ) + docker_image = DockerImage.objects.create( + name="Python", + file="docker_images/Dockerfile.python", + owner=create_admin( + id=55, + first_name="John", + last_name="Doe", + email="john@doe.com" + ) + ) + check = ExtraCheck.objects.create( + name="test extra check", + project=project, + docker_image=docker_image, + file="testscript.sh", + ) + + response = self.client.get( + reverse("extra-check-detail", args=[str(check.id)]), follow=True + ) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore + + content_json = json.loads(response.content.decode("utf-8")) + + self.assertEqual(int(content_json["id"]), check.id) + self.assertEqual( + content_json["project"], + settings.TESTING_BASE_LINK + reverse("project-detail", args=[str(project.id)]), + ) + self.assertEqual( + content_json["docker_image"], + settings.TESTING_BASE_LINK + reverse("docker-image-detail", args=[str(docker_image.id)]), + ) + self.assertEqual( + content_json["file"], + settings.TESTING_BASE_LINK + check.file.url, + ) def test_project_groups(self): """ @@ -600,7 +603,7 @@ def test_project_groups(self): ) self.assertEqual(response.status_code, 200) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore content_json = json.loads(response.content.decode("utf-8")) @@ -609,39 +612,39 @@ def test_project_groups(self): self.assertEqual(int(content_json[0]["id"]), group1.id) self.assertEqual(int(content_json[1]["id"]), group2.id) - # def test_project_submissions(self): - # """ - # Able to retrieve a list of submissions of a project after creating it. - # """ - # course = create_course(name="test course", academic_startyear=2024) - # project = create_project( - # name="test project", - # description="test description", - # visible=True, - # archived=False, - # days=7, - # course=course, - # ) + def test_project_submissions(self): + """ + Able to retrieve a list of submissions of a project after creating it. + """ + course = create_course(name="test course", academic_startyear=2024) + project = create_project( + name="test project", + description="test description", + visible=True, + archived=False, + days=7, + course=course, + ) - # group1 = create_group(project=project, score=0) - # group2 = create_group(project=project, score=0) + group1 = create_group(project=project, score=0) + group2 = create_group(project=project, score=0) - # submission1 = create_submission(submission_number=1, group=group1, structure_checks_passed=True) - # submission2 = create_submission(submission_number=2, group=group2, structure_checks_passed=False) + submission1 = create_submission(group=group1, zip="group1.zip") + submission2 = create_submission(group=group2, zip="group2.zip") - # response = self.client.get( - # reverse("project-submissions", args=[str(project.id)]), follow=True - # ) + response = self.client.get( + reverse("project-submissions", args=[str(project.id)]), follow=True + ) - # self.assertEqual(response.status_code, 200) - # self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.status_code, 200) + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore - # content_json = json.loads(response.content.decode("utf-8")) + content_json = json.loads(response.content.decode("utf-8")) - # self.assertEqual(len(content_json), 2) + self.assertEqual(len(content_json), 2) - # self.assertEqual(int(content_json[0]["id"]), submission1.id) - # self.assertEqual(int(content_json[1]["id"]), submission2.id) + self.assertEqual(int(content_json[0]["id"]), submission1.id) + self.assertEqual(int(content_json[1]["id"]), submission2.id) def test_cant_join_locked_groups(self): """Should not be able to add a student to a group if the groups are locked.""" @@ -712,7 +715,7 @@ def setUp(self) -> None: email="Test@gmail.com", ) - self.client.force_authenticate(self.user) + self.client.force_authenticate(self.user) # type: ignore def test_create_groups(self): """Able to create groups for a project.""" @@ -749,147 +752,152 @@ def test_create_groups(self): # Assert that the groups were created self.assertEqual(project.groups.count(), 3) - # def test_submission_status_non_empty_groups(self): - # """Submission status returns the correct amount of non empty groups participating in the project.""" - # course = create_course(name="test course", academic_startyear=2024) - # project = create_project( - # name="test", - # description="descr", - # visible=True, - # archived=False, - # days=7, - # course=course, - # ) - - # response = self.client.get( - # reverse("project-groups", args=[str(project.id)]), follow=True - # ) - - # # Make sure you cannot retrieve the submission status for a project that is not yours - # self.assertEqual(response.status_code, 403) - - # # Add the teacher to the course - # course.teachers.add(self.user) - - # # Create example students - # student1 = create_student( - # id=1, first_name="John", last_name="Doe", email="john.doe@example.com", student_id="0100" - # ) - # student2 = create_student( - # id=2, first_name="Jane", last_name="Doe", email="jane.doe@example.com", student_id="0200" - # ) - - # # Create example groups - # group1 = create_group(project=project) - # group2 = create_group(project=project) - # group3 = create_group(project=project) # noqa: F841 - - # # Add the students to some of the groups - # group1.students.add(student1) - # group2.students.add(student2) - - # response = self.client.get( - # reverse("project-submission-status", args=[str(project.id)]), follow=True - # ) - - # self.assertEqual(response.status_code, 200) - - # # Only two of the three created groups contain at least one student - # self.assertEqual( - # response.data, - # {"non_empty_groups": 2, "groups_submitted": 0, "submissions_passed": 0}, - # ) - - # def test_submission_status_groups_submitted_and_passed_checks(self): - # """Retrieve the submission status for a project.""" - # course = create_course(name="test course", academic_startyear=2024) - # project = create_project( - # name="test", - # description="descr", - # visible=True, - # archived=False, - # days=7, - # course=course, - # ) - - # response = self.client.get( - # reverse("project-groups", args=[str(project.id)]), follow=True - # ) - - # # Make sure you cannot retrieve the submission status for a project that is not yours - # self.assertEqual(response.status_code, 403) - - # # Add the teacher to the course - # course.teachers.add(self.user) - - # # Create example students - # student1 = create_student( - # id=1, first_name="John", last_name="Doe", email="john.doe@example.com", student_id="0100" - # ) - # student2 = create_student( - # id=2, first_name="Jane", last_name="Doe", email="jane.doe@example.com", student_id="0200" - # ) - # student3 = create_student( - # id=3, first_name="Joe", last_name="Doe", email="Joe.doe@example.com" - # ) - - # # Create example groups - # group1 = create_group(project=project) - # group2 = create_group(project=project) - # group3 = create_group(project=project) - - # # Add students to the groups - # group1.students.add(student1) - # group2.students.add(student2) - # group3.students.add(student3) - - # # Create submissions for certain groups - # create_submission( - # submission_number=1, group=group1, structure_checks_passed=True - # ) - # create_submission( - # submission_number=2, group=group3, structure_checks_passed=False - # ) - - # response = self.client.get( - # reverse("project-submission-status", args=[str(project.id)]), follow=True - # ) - - # self.assertEqual(response.status_code, 200) - # self.assertEqual( - # response.data, - # {"non_empty_groups": 3, "groups_submitted": 2, "submissions_passed": 1}, - # ) - - # def test_retrieve_list_submissions(self): - # """Able to retrieve a list of submissions for a project.""" - # course = create_course(name="test course", academic_startyear=2024) - # project = create_project( - # name="test", - # description="descr", - # visible=True, - # archived=False, - # days=7, - # course=course, - # ) - # course.teachers.add(self.user) - - # group = create_group(project=project) - - # create_submission( - # submission_number=1, group=group, structure_checks_passed=True - # ) - - # response = self.client.get( - # reverse("project-submissions", args=[str(project.id)]), follow=True - # ) - - # self.assertEqual(response.status_code, 200) - # self.assertEqual(response.accepted_media_type, "application/json") - - # content_json = json.loads(response.content.decode("utf-8")) - - # self.assertEqual(len(content_json), 1) + def test_submission_status_non_empty_groups(self): + """Submission status returns the correct amount of non empty groups participating in the project.""" + course = create_course(name="test course", academic_startyear=2024) + project = create_project( + name="test", + description="descr", + visible=True, + archived=False, + days=7, + course=course, + ) + + response = self.client.get( + reverse("project-groups", args=[str(project.id)]), follow=True + ) + + # Make sure you cannot retrieve the submission status for a project that is not yours + self.assertEqual(response.status_code, 403) + + # Add the teacher to the course + course.teachers.add(self.user) + + # Create example students + student1 = create_student( + id=1, first_name="John", last_name="Doe", email="john.doe@example.com", student_id="0100" + ) + student2 = create_student( + id=2, first_name="Jane", last_name="Doe", email="jane.doe@example.com", student_id="0200" + ) + + # Create example groups + group1 = create_group(project=project) + group2 = create_group(project=project) + group3 = create_group(project=project) # noqa: F841 + + # Add the students to some of the groups + group1.students.add(student1) + group2.students.add(student2) + + response = self.client.get( + reverse("project-detail", args=[str(project.id)]), follow=True + ) + + self.assertEqual(response.status_code, 200) + + content_json = json.loads(response.content.decode("utf-8")) + + # Only two of the three created groups contain at least one student + self.assertEqual( + content_json["status"], + {"non_empty_groups": 2, "groups_submitted": 0, "submissions_passed": 0}, + ) + + def test_submission_status_groups_submitted_and_passed_checks(self): + """Retrieve the submission status for a project.""" + course = create_course(name="test course", academic_startyear=2024) + project = create_project( + name="test", + description="descr", + visible=True, + archived=False, + days=7, + course=course, + ) + + response = self.client.get( + reverse("project-groups", args=[str(project.id)]), follow=True + ) + + # Make sure you cannot retrieve the submission status for a project that is not yours + self.assertEqual(response.status_code, 403) + + # Add the teacher to the course + course.teachers.add(self.user) + + # Create example students + student1 = create_student( + id=1, first_name="John", last_name="Doe", email="john.doe@example.com", student_id="0100" + ) + student2 = create_student( + id=2, first_name="Jane", last_name="Doe", email="jane.doe@example.com", student_id="0200" + ) + student3 = create_student( + id=3, first_name="Joe", last_name="Doe", email="Joe.doe@example.com" + ) + + # Create example groups + group1 = create_group(project=project) + group2 = create_group(project=project) + group3 = create_group(project=project) + + # Add students to the groups + group1.students.add(student1) + group2.students.add(student2) + group3.students.add(student3) + + # Create submissions for certain groups + create_submission( + group=group1, zip="group1.zip" + ) + create_submission( + group=group3, zip="group3.zip" + ) + + response = self.client.get( + reverse("project-detail", args=[str(project.id)]), follow=True + ) + + self.assertEqual(response.status_code, 200) + + content_json = json.loads(response.content.decode("utf-8")) + + self.assertEqual( + content_json["status"], + {"non_empty_groups": 3, "groups_submitted": 2, "submissions_passed": 2}, + ) + + def test_retrieve_list_submissions(self): + """Able to retrieve a list of submissions for a project.""" + course = create_course(name="test course", academic_startyear=2024) + project = create_project( + name="test", + description="descr", + visible=True, + archived=False, + days=7, + course=course, + ) + course.teachers.add(self.user) + + group = create_group(project=project) + + create_submission( + group=group, zip="group.zip" + ) + + response = self.client.get( + reverse("project-submissions", args=[str(project.id)]), follow=True + ) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore + + content_json = json.loads(response.content.decode("utf-8")) + + self.assertEqual(len(content_json), 1) class ProjectModelTestsAsStudent(APITestCase): @@ -902,7 +910,7 @@ def setUp(self) -> None: email="Bobke.Peeters@gmail.com", ) - self.client.force_authenticate(self.user) + self.client.force_authenticate(self.user) # type: ignore def test_try_to_create_groups(self): """Not able to create groups for a project.""" diff --git a/backend/api/tests/test_student.py b/backend/api/tests/test_student.py index e4027563..20a4eb23 100644 --- a/backend/api/tests/test_student.py +++ b/backend/api/tests/test_student.py @@ -1,15 +1,17 @@ import json -from django.urls import reverse -from rest_framework.test import APITestCase + from api.models.student import Student -from api.tests.helpers import create_student, create_course, create_faculty, create_user +from api.tests.helpers import (create_course, create_faculty, create_student, + create_user) from authentication.models import User +from django.urls import reverse +from rest_framework.test import APITestCase class StudentModelTests(APITestCase): def setUp(self) -> None: - self.client.force_authenticate( + self.client.force_authenticate( # type: ignore User.get_dummy_admin() ) @@ -21,7 +23,7 @@ def test_no_student(self): response_root = self.client.get(reverse("student-list"), follow=True) self.assertEqual(response_root.status_code, 200) # Assert that the response is JSON - self.assertEqual(response_root.accepted_media_type, "application/json") + self.assertEqual(response_root.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response_root.content.decode("utf-8")) # Assert that the parsed JSON is an empty list @@ -99,7 +101,7 @@ def test_student_exists(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -133,7 +135,7 @@ def test_multiple_students(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -172,7 +174,7 @@ def test_student_detail_view(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -206,7 +208,7 @@ def test_student_faculty(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -224,7 +226,7 @@ def test_student_faculty(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -263,7 +265,7 @@ def test_student_courses(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -281,7 +283,7 @@ def test_student_courses(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) diff --git a/backend/api/tests/test_submission.py b/backend/api/tests/test_submission.py index ca5a2660..b1f42109 100644 --- a/backend/api/tests/test_submission.py +++ b/backend/api/tests/test_submission.py @@ -1,306 +1,251 @@ import json -from datetime import timedelta -from api.models.project import Project -from api.models.submission import Submission -from api.tests.helpers import create_course, create_group, create_project +from api.tests.helpers import (create_course, create_group, + create_past_project, create_project, + create_submission) from authentication.models import User from django.core.files.uploadedfile import SimpleUploadedFile from django.urls import reverse -from django.utils import timezone from django.utils.translation import gettext from rest_framework.test import APITestCase - - -def create_past_project(name, description, days, course, days_start_date): - """Create a Project with the given arguments.""" - deadline = timezone.now() + timedelta(days=days) - start_date = timezone.now() + timedelta(days=days_start_date) - - return Project.objects.create( - name=name, description=description, deadline=deadline, course=course, score_visible=True, start_date=start_date - ) - - -def create_submission(group, submission_number): - """Create a Submission with the given arguments.""" - return Submission.objects.create( - group=group, submission_number=submission_number, submission_time=timezone.now(), structure_checks_passed=True - ) - - -# def create_submission_file(submission, file): -# """Create an SubmissionFile with the given arguments.""" -# return SubmissionFile.objects.create(submission=submission, file=file) +from ypovoli.settings import TESTING_BASE_LINK class SubmissionModelTests(APITestCase): - # def setUp(self) -> None: - # self.client.force_authenticate( - # User.get_dummy_admin() - # ) + def setUp(self) -> None: + self.client.force_authenticate( # type: ignore + User.get_dummy_admin() + ) - # def test_no_submission(self): - # """ - # able to retrieve no submission before publishing it. - # """ + def test_no_submission(self): + """ + able to retrieve no submission before publishing it. + """ - # response_root = self.client.get(reverse("submission-list"), follow=True) - # self.assertEqual(response_root.status_code, 200) - # # Assert that the response is JSON - # self.assertEqual(response_root.accepted_media_type, "application/json") - # # Parse the JSON content from the response - # content_json = json.loads(response_root.content.decode("utf-8")) - # # Assert that the parsed JSON is an empty list - # self.assertEqual(content_json, []) + course = create_course(name="sel2", academic_startyear=2023) + project = create_project( + name="Project 1", description="Description 1", days=7, course=course + ) - # def test_submission_exists(self): - # """ - # Able to retrieve a single submission after creating it. - # """ - # course = create_course(name="sel2", academic_startyear=2023) - # project = create_project( - # name="Project 1", description="Description 1", days=7, course=course - # ) - # group = create_group(project=project, score=10) - # submission = create_submission(group=group, submission_number=1) + response_root = self.client.get(reverse("project-submissions", args=[str(project.id)]), follow=True) + self.assertEqual(response_root.status_code, 200) + # Assert that the response is JSON + self.assertEqual(response_root.accepted_media_type, "application/json") # type: ignore + # Parse the JSON content from the response + content_json = json.loads(response_root.content.decode("utf-8")) + # Assert that the parsed JSON is an empty list + self.assertEqual(content_json, []) - # # Make a GET request to retrieve the submission - # response = self.client.get(reverse("submission-list"), follow=True) + def test_submission_exists(self): + """ + Able to retrieve a single submission after creating it. + """ + course = create_course(name="sel2", academic_startyear=2023) + project = create_project( + name="Project 1", description="Description 1", days=7, course=course + ) + group = create_group(project=project, score=10) + submission = create_submission(group=group, zip="zip1") - # # Check if the response was successful - # self.assertEqual(response.status_code, 200) + # Make a GET request to retrieve the submission + response = self.client.get(reverse("project-submissions", args=[str(project.id)]), follow=True) - # # Assert that the response is JSON - # self.assertEqual(response.accepted_media_type, "application/json") + # Check if the response was successful + self.assertEqual(response.status_code, 200) - # # Parse the JSON content from the response - # content_json = json.loads(response.content.decode("utf-8")) + # Assert that the response is JSON + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore - # # Assert that the parsed JSON is a list with one submission - # self.assertEqual(len(content_json), 1) + # Parse the JSON content from the response + content_json = json.loads(response.content.decode("utf-8")) - # # Assert the details of the retrieved submission - # # match the created submission - # retrieved_submission = content_json[0] - # expected_group_url = settings.TESTING_BASE_LINK + reverse( - # "group-detail", args=[str(group.id)] - # ) - # self.assertEqual(int(retrieved_submission["id"]), submission.id) - # self.assertEqual( - # int(retrieved_submission["submission_number"]), submission.submission_number - # ) - # self.assertEqual(retrieved_submission["group"], expected_group_url) - # self.assertEqual(retrieved_submission["structure_checks_passed"], submission.structure_checks_passed) + # Assert that the parsed JSON is a list with one submission + self.assertEqual(len(content_json), 1) - # def test_multiple_submission_exists(self): - # """ - # Able to retrieve multiple submissions after creating them. - # """ - # course = create_course(name="sel2", academic_startyear=2023) - # project = create_project( - # name="Project 1", description="Description 1", days=7, course=course - # ) - # group = create_group(project=project, score=10) - # submission1 = create_submission(group=group, submission_number=1) - - # submission2 = create_submission(group=group, submission_number=2) - - # # Make a GET request to retrieve the submission - # response = self.client.get(reverse("submission-list"), follow=True) + # Assert the details of the retrieved submission + # match the created submission + retrieved_submission = content_json[0] + expected_group_url = TESTING_BASE_LINK + reverse( + "group-detail", args=[str(group.id)] + ) + self.assertEqual(int(retrieved_submission["id"]), submission.id) + self.assertEqual(retrieved_submission["group"], expected_group_url) - # # Check if the response was successful - # self.assertEqual(response.status_code, 200) + def test_multiple_submission_exists(self): + """ + Able to retrieve multiple submissions after creating them. + """ + course = create_course(name="sel2", academic_startyear=2023) + project = create_project( + name="Project 1", description="Description 1", days=7, course=course + ) + group = create_group(project=project, score=10) + submission1 = create_submission(group=group, zip="zip1") - # # Assert that the response is JSON - # self.assertEqual(response.accepted_media_type, "application/json") + submission2 = create_submission(group=group, zip="zip2") - # # Parse the JSON content from the response - # content_json = json.loads(response.content.decode("utf-8")) + # Make a GET request to retrieve the submission + response = self.client.get(reverse("project-submissions", args=[str(project.id)]), follow=True) - # # Assert that the parsed JSON is a list with one submission - # self.assertEqual(len(content_json), 2) + # Check if the response was successful + self.assertEqual(response.status_code, 200) - # # Assert the details of the retrieved submission - # # match the created submission - # retrieved_submission = content_json[0] - # expected_group_url = settings.TESTING_BASE_LINK + reverse( - # "group-detail", args=[str(group.id)] - # ) - # self.assertEqual(int(retrieved_submission["id"]), submission1.id) - # self.assertEqual( - # int(retrieved_submission["submission_number"]), - # submission1.submission_number, - # ) - # self.assertEqual(retrieved_submission["group"], expected_group_url) + # Assert that the response is JSON + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore - # retrieved_submission = content_json[1] - # expected_group_url = settings.TESTING_BASE_LINK + reverse( - # "group-detail", args=[str(group.id)] - # ) - # self.assertEqual(int(retrieved_submission["id"]), submission2.id) - # self.assertEqual( - # int(retrieved_submission["submission_number"]), - # submission2.submission_number, - # ) - # self.assertEqual(retrieved_submission["group"], expected_group_url) + # Parse the JSON content from the response + content_json = json.loads(response.content.decode("utf-8")) - # def test_submission_detail_view(self): - # """ - # Able to retrieve details of a single submission. - # """ - # course = create_course(name="sel2", academic_startyear=2023) - # project = create_project( - # name="Project 1", description="Description 1", days=7, course=course - # ) - # group = create_group(project=project, score=10) - # submission = create_submission(group=group, submission_number=1) + # Assert that the parsed JSON is a list with one submission + self.assertEqual(len(content_json), 2) - # # Make a GET request to retrieve the submission - # response = self.client.get( - # reverse("submission-detail", args=[str(submission.id)]), follow=True - # ) + # Assert the details of the retrieved submission + # match the created submission + retrieved_submission = content_json[0] + expected_group_url = TESTING_BASE_LINK + reverse( + "group-detail", args=[str(group.id)] + ) + self.assertEqual(int(retrieved_submission["id"]), submission1.id) + self.assertEqual(retrieved_submission["group"], expected_group_url) - # # Check if the response was successful - # self.assertEqual(response.status_code, 200) + retrieved_submission = content_json[1] + expected_group_url = TESTING_BASE_LINK + reverse( + "group-detail", args=[str(group.id)] + ) + self.assertEqual(int(retrieved_submission["id"]), submission2.id) + self.assertEqual(retrieved_submission["group"], expected_group_url) - # # Assert that the response is JSON - # self.assertEqual(response.accepted_media_type, "application/json") + def test_submission_detail_view(self): + """ + Able to retrieve details of a single submission. + """ + course = create_course(name="sel2", academic_startyear=2023) + project = create_project( + name="Project 1", description="Description 1", days=7, course=course + ) + group = create_group(project=project, score=10) + submission = create_submission(group=group, zip="zip1") - # # Parse the JSON content from the response - # content_json = json.loads(response.content.decode("utf-8")) + # Make a GET request to retrieve the submission + response = self.client.get( + reverse("submission-detail", args=[str(submission.id)]), follow=True + ) - # # Assert the details of the retrieved submission - # # match the created submission - # retrieved_submission = content_json - # expected_group_url = settings.TESTING_BASE_LINK + reverse( - # "group-detail", args=[str(group.id)] - # ) - # self.assertEqual(int(retrieved_submission["id"]), submission.id) - # self.assertEqual( - # int(retrieved_submission["submission_number"]), submission.submission_number - # ) - # self.assertEqual(retrieved_submission["group"], expected_group_url) + # Check if the response was successful + self.assertEqual(response.status_code, 200) - # def test_submission_group(self): - # """ - # Able to retrieve group of a single submission. - # """ - # course = create_course(name="sel2", academic_startyear=2023) - # project = create_project( - # name="Project 1", description="Description 1", days=7, course=course - # ) - # group = create_group(project=project, score=10) - # submission = create_submission(group=group, submission_number=1) + # Assert that the response is JSON + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore - # # Make a GET request to retrieve the submission - # response = self.client.get( - # reverse("submission-detail", args=[str(submission.id)]), follow=True - # ) + # Parse the JSON content from the response + content_json = json.loads(response.content.decode("utf-8")) - # # Check if the response was successful - # self.assertEqual(response.status_code, 200) + # Assert the details of the retrieved submission + # match the created submission + retrieved_submission = content_json + expected_group_url = TESTING_BASE_LINK + reverse( + "group-detail", args=[str(group.id)] + ) + self.assertEqual(int(retrieved_submission["id"]), submission.id) + self.assertEqual(retrieved_submission["group"], expected_group_url) - # # Assert that the response is JSON - # self.assertEqual(response.accepted_media_type, "application/json") + def test_submission_group(self): + """ + Able to retrieve group of a single submission. + """ + course = create_course(name="sel2", academic_startyear=2023) + project = create_project( + name="Project 1", description="Description 1", days=7, course=course + ) + group = create_group(project=project, score=10) + submission = create_submission(group=group, zip="zip1") - # # Parse the JSON content from the response - # content_json = json.loads(response.content.decode("utf-8")) + # Make a GET request to retrieve the submission + response = self.client.get( + reverse("submission-detail", args=[str(submission.id)]), follow=True + ) - # # Assert the details of the retrieved submission - # # match the created submission - # retrieved_submission = content_json - # self.assertEqual(int(retrieved_submission["id"]), submission.id) - # self.assertEqual( - # int(retrieved_submission["submission_number"]), submission.submission_number - # ) + # Check if the response was successful + self.assertEqual(response.status_code, 200) - # response = self.client.get(content_json["group"], follow=True) + # Assert that the response is JSON + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore - # # Check if the response was successful - # self.assertEqual(response.status_code, 200) + # Parse the JSON content from the response + content_json = json.loads(response.content.decode("utf-8")) - # # Assert that the response is JSON - # self.assertEqual(response.accepted_media_type, "application/json") + # Assert the details of the retrieved submission + # match the created submission + retrieved_submission = content_json + self.assertEqual(int(retrieved_submission["id"]), submission.id) - # # Parse the JSON content from the response - # content_json = json.loads(response.content.decode("utf-8")) + response = self.client.get(content_json["group"], follow=True) - # expected_project_url = settings.TESTING_BASE_LINK + reverse( - # "project-detail", args=[str(project.id)] - # ) + # Check if the response was successful + self.assertEqual(response.status_code, 200) - # self.assertEqual(int(content_json["id"]), group.id) - # self.assertEqual(content_json["project"], expected_project_url) - # self.assertEqual(content_json["score"], group.score) + # Assert that the response is JSON + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore - # def test_submission_extra_checks(self): - # """ - # Able to retrieve extra checks of a single submission. - # """ - # course = create_course(name="sel2", academic_startyear=2023) - # project = create_project( - # name="Project 1", description="Description 1", days=7, course=course - # ) - # group = create_group(project=project, score=10) - # submission = create_submission(group=group, submission_number=1) - # extra_check = ExtraCheck.objects.create( - # project=project, run_script="test.py" - # ) - # extra_check_result = ExtraChecksResult.objects.create( - # submission=submission, extra_check=extra_check, passed=True - # ) + # Parse the JSON content from the response + content_json = json.loads(response.content.decode("utf-8")) - # # Make a GET request to retrieve the submission - # response = self.client.get( - # reverse("submission-detail", args=[str(submission.id)]), follow=True - # ) + self.assertEqual(int(content_json["id"]), group.id) + self.assertEqual(content_json["score"], group.score) - # # Check if the response was successful - # self.assertEqual(response.status_code, 200) + def test_submission_extra_checks(self): + """ + Able to retrieve extra checks of a single submission. + """ + course = create_course(name="sel2", academic_startyear=2023) + project = create_project( + name="Project 1", description="Description 1", days=7, course=course + ) + group = create_group(project=project, score=10) + submission = create_submission(group=group, zip="zip1") - # # Assert that the response is JSON - # self.assertEqual(response.accepted_media_type, "application/json") + # Make a GET request to retrieve the submission + response = self.client.get( + reverse("submission-detail", args=[str(submission.id)]), follow=True + ) - # # Parse the JSON content from the response - # content_json = json.loads(response.content.decode("utf-8")) + # Check if the response was successful + self.assertEqual(response.status_code, 200) - # # Assert the details of the retrieved submission - # # match the created submission - # retrieved_submission = content_json - # self.assertEqual(int(retrieved_submission["id"]), submission.id) + # Assert that the response is JSON + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore - # # Extra check that is part of the project - # retrieved_extra_check = content_json["extra_checks_results"][0] + # Parse the JSON content from the response + content_json = json.loads(response.content.decode("utf-8")) - # self.assertEqual( - # retrieved_extra_check["passed"], extra_check_result.passed - # ) + # Assert the details of the retrieved submission + # match the created submission + retrieved_submission = content_json + self.assertEqual(int(retrieved_submission["id"]), submission.id) - # def test_submission_before_deadline(self): - # """ - # Able to subbmit to a project before the deadline. - # """ - # zip_file_path = "data/testing/tests/mixed.zip" + def test_submission_before_deadline(self): + """ + Able to subbmit to a project before the deadline. + """ + zip_file_path = "data/testing/tests/mixed.zip" - # with open(zip_file_path, 'rb') as file: - # files = {'files': SimpleUploadedFile('mixed.zip', file.read())} - # course = create_course(name="sel2", academic_startyear=2023) - # project = create_project( - # name="Project 1", description="Description 1", days=7, course=course - # ) - # group = create_group(project=project, score=10) + with open(zip_file_path, 'rb') as file: + files = {'files': SimpleUploadedFile('mixed.zip', file.read())} + course = create_course(name="sel2", academic_startyear=2023) + project = create_project( + name="Project 1", description="Description 1", days=7, course=course + ) + group = create_group(project=project, score=10) - # response = self.client.post( - # reverse("group-submissions", args=[str(group.id)]), - # files, - # follow=True, - # ) + response = self.client.post( + reverse("group-submissions", args=[str(group.id)]), + files, + follow=True, + ) - # self.assertEqual(response.status_code, 200) - # self.assertEqual(response.accepted_media_type, "application/json") - # self.assertEqual(json.loads(response.content), {"message": gettext("group.success.submissions.add")}) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore def test_submission_after_deadline(self): """ @@ -325,7 +270,7 @@ def test_submission_after_deadline(self): ) self.assertEqual(response.status_code, 400) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore self.assertEqual(json.loads(response.content), { 'non_field_errors': [gettext("project.error.submissions.past_project")]}) @@ -396,7 +341,7 @@ def test_submission_invisible_project(self): ) self.assertEqual(response.status_code, 400) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore self.assertEqual(json.loads(response.content), { 'non_field_errors': [gettext("project.error.submissions.non_visible_project")]}) @@ -426,6 +371,6 @@ def test_submission_archived_project(self): ) self.assertEqual(response.status_code, 400) - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore self.assertEqual(json.loads(response.content), { 'non_field_errors': [gettext("project.error.submissions.archived_project")]}) diff --git a/backend/api/tests/test_teacher.py b/backend/api/tests/test_teacher.py index 6a439a88..96c5fbab 100644 --- a/backend/api/tests/test_teacher.py +++ b/backend/api/tests/test_teacher.py @@ -1,13 +1,14 @@ import json + +from api.tests.helpers import create_course, create_faculty, create_teacher +from authentication.models import User from django.urls import reverse from rest_framework.test import APITestCase -from api.tests.helpers import create_teacher, create_course, create_faculty -from authentication.models import User class TeacherModelTests(APITestCase): def setUp(self) -> None: - self.client.force_authenticate( + self.client.force_authenticate( # type: ignore User.get_dummy_admin() ) @@ -19,7 +20,7 @@ def test_no_teacher(self): response_root = self.client.get(reverse("teacher-list"), follow=True) self.assertEqual(response_root.status_code, 200) # Assert that the response is JSON - self.assertEqual(response_root.accepted_media_type, "application/json") + self.assertEqual(response_root.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response_root.content.decode("utf-8")) # Assert that the parsed JSON is an empty list @@ -40,7 +41,7 @@ def test_teacher_exists(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -74,7 +75,7 @@ def test_multiple_teachers(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -112,7 +113,7 @@ def test_teacher_detail_view(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -146,7 +147,7 @@ def test_teacher_faculty(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -164,7 +165,7 @@ def test_teacher_faculty(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -203,7 +204,7 @@ def test_teacher_courses(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) @@ -221,7 +222,7 @@ def test_teacher_courses(self): self.assertEqual(response.status_code, 200) # Assert that the response is JSON - self.assertEqual(response.accepted_media_type, "application/json") + self.assertEqual(response.accepted_media_type, "application/json") # type: ignore # Parse the JSON content from the response content_json = json.loads(response.content.decode("utf-8")) diff --git a/backend/data/testing/docker_images/Dockerfile.python b/backend/data/testing/docker_images/Dockerfile.python new file mode 100644 index 00000000..b911dee2 --- /dev/null +++ b/backend/data/testing/docker_images/Dockerfile.python @@ -0,0 +1 @@ +FROM python:3.11.4-alpine3.18 diff --git a/test.yml b/test.yml index 4d90cf7c..0f274abd 100644 --- a/test.yml +++ b/test.yml @@ -59,7 +59,7 @@ services: build: context: $BACKEND_DIR dockerfile: Dockerfile - command: sh -c "poetry install && celery -A ypovoli worker -l DEBUG" + command: sh -c "./setup.sh && celery -A ypovoli worker -l DEBUG" volumes: - $BACKEND_DIR:/code depends_on: