diff --git a/pedagogy/api.py b/pedagogy/api.py index 24f5919b..91acb817 100644 --- a/pedagogy/api.py +++ b/pedagogy/api.py @@ -29,14 +29,11 @@ class UeController(ControllerBase): response=UeSchema, ) def fetch_from_utbm_api( - self, - code: str, - lang: Query[str] = "fr", - year: Query[Annotated[int, Ge(2010)] | None] = None, + self, code: str, year: Query[Annotated[int, Ge(2010)] | None] = None ): """Fetch UE data from the UTBM API and returns it after some parsing.""" with UtbmApiClient() as client: - res = client.find_ue(lang, code, year) + res = client.find_ue(code, year) if res is None: raise NotFound return res diff --git a/pedagogy/schemas.py b/pedagogy/schemas.py index 34c2f5a9..592c134a 100644 --- a/pedagogy/schemas.py +++ b/pedagogy/schemas.py @@ -190,6 +190,7 @@ class UeFilterSchema(FilterSchema): return Q(semester__in=value) def filter_is_open(self, value: bool | None) -> Q: # noqa: FBT001 + """Filter by open/closed status.""" if value is None: return Q() if not value: diff --git a/pedagogy/tests/test_api.py b/pedagogy/tests/test_api.py index 2726252d..2b5cda44 100644 --- a/pedagogy/tests/test_api.py +++ b/pedagogy/tests/test_api.py @@ -1,8 +1,6 @@ -import json - from django.conf import settings +from django.core.management import call_command from django.test import TestCase -from django.test.testcases import call_command from django.urls import reverse from model_bakery import baker from model_bakery.recipe import Recipe @@ -17,7 +15,7 @@ class TestUESearch(TestCase): @classmethod def setUpTestData(cls): - cls.root = User.objects.get(username="root") + cls.root = baker.make(User, is_superuser=True) cls.url = reverse("api:fetch_ues") ue_recipe = Recipe(UE, author=cls.root) ues = [ @@ -92,10 +90,10 @@ class TestUESearch(TestCase): def test_format(self): """Test that the return data format is correct""" self.client.force_login(self.root) - res = self.client.get(self.url + "?search=PA00") + res = self.client.get(self.url, query_params={"search": "PA00"}) ue = UE.objects.get(code="PA00") assert res.status_code == 200 - assert json.loads(res.content) == { + assert res.json() == { "count": 1, "next": None, "previous": None, @@ -121,79 +119,77 @@ class TestUESearch(TestCase): def test_search_by_text(self): self.client.force_login(self.root) for query, expected in ( - # UE code search case insensitive + # UE code search case-insensitive ("m", {"MT01", "MT10"}), ("M", {"MT01", "MT10"}), ("mt", {"MT01", "MT10"}), ("MT", {"MT01", "MT10"}), - ("algèbre", {"MT01"}), # Title search case insensitive + ("algèbre", {"MT01"}), # Title search case-insensitive # Manager search ("moss", {"TNEV"}), ("francky", {"DA50", "AP4A"}), ): - res = self.client.get(self.url + f"?search={query}") + res = self.client.get(self.url, query_params={"search": query}) assert res.status_code == 200 - assert {ue["code"] for ue in json.loads(res.content)["results"]} == expected + assert {ue["code"] for ue in res.json()["results"]} == expected def test_search_by_credit_type(self): self.client.force_login(self.root) - res = self.client.get(self.url + "?credit_type=CS") + res = self.client.get(self.url, query_params={"credit_type": "CS"}) assert res.status_code == 200 - codes = [ue["code"] for ue in json.loads(res.content)["results"]] + codes = [ue["code"] for ue in res.json()["results"]] assert codes == ["AP4A", "MT01", "PHYS11"] - res = self.client.get(self.url + "?credit_type=CS&credit_type=OM") + res = self.client.get(self.url, query_params={"credit_type": ["CS", "OM"]}) assert res.status_code == 200 - codes = {ue["code"] for ue in json.loads(res.content)["results"]} + codes = {ue["code"] for ue in res.json()["results"]} assert codes == {"AP4A", "MT01", "PHYS11", "PA00"} def test_search_by_semester(self): self.client.force_login(self.root) - res = self.client.get(self.url + "?semester=SPRING") + res = self.client.get(self.url, query_params={"semester": "SPRING"}) assert res.status_code == 200 - codes = {ue["code"] for ue in json.loads(res.content)["results"]} + codes = {ue["code"] for ue in res.json()["results"]} assert codes == {"DA50", "TNEV", "PA00"} def test_search_multiple_filters(self): self.client.force_login(self.root) res = self.client.get( - self.url + "?semester=AUTUMN&credit_type=CS&department=TC" + self.url, + query_params={ + "semester": "AUTUMN", + "credit_type": "CS", + "department": "TC", + }, ) assert res.status_code == 200 - codes = {ue["code"] for ue in json.loads(res.content)["results"]} + codes = {ue["code"] for ue in res.json()["results"]} assert codes == {"MT01", "PHYS11"} def test_search_fails(self): self.client.force_login(self.root) - res = self.client.get(self.url + "?credit_type=CS&search=DA") + res = self.client.get( + self.url, query_params={"search": "DA", "credit_type": "CS"} + ) assert res.status_code == 200 - assert json.loads(res.content)["results"] == [] + assert res.json()["results"] == [] + + def test_search_closed_status(self): + # Simple heuristic : take a UE, and mark everything before it as closed + closed_ue = UE.objects.order_by("id")[2] + UE.objects.filter(id__lte=closed_ue.id).update(semester="CLOSED") - def test_search_pa00_fail(self): self.client.force_login(self.root) - # Search with UE code - response = self.client.get(reverse("pedagogy:guide"), {"search": "IFC"}) - self.assertNotContains(response, text="PA00") - # Search with first letter of UE code - response = self.client.get(reverse("pedagogy:guide"), {"search": "I"}) - self.assertNotContains(response, text="PA00") + res = self.client.get(self.url, query_params={"is_open": False}) + assert res.status_code == 200 + ids = {ue["id"] for ue in res.json()["results"]} + assert ids == set( + UE.objects.filter(semester="CLOSED").values_list("id", flat=True) + ) - # Search with UE manager - response = self.client.get(reverse("pedagogy:guide"), {"search": "GILLES"}) - self.assertNotContains(response, text="PA00") - - # Search with department - response = self.client.get(reverse("pedagogy:guide"), {"department": "TC"}) - self.assertNotContains(response, text="PA00") - - # Search with semester - response = self.client.get(reverse("pedagogy:guide"), {"semester": "CLOSED"}) - self.assertNotContains(response, text="PA00") - - # Search with language - response = self.client.get(reverse("pedagogy:guide"), {"language": "EN"}) - self.assertNotContains(response, text="PA00") - - # Search with credit type - response = self.client.get(reverse("pedagogy:guide"), {"credit_type": "TM"}) - self.assertNotContains(response, text="PA00") + res = self.client.get(self.url, query_params={"is_open": True}) + assert res.status_code == 200 + ids = {ue["id"] for ue in res.json()["results"]} + assert ids == set( + UE.objects.exclude(semester="CLOSED").values_list("id", flat=True) + )