From 19a2aa3c8c07b4cb713226e7d07a8b5d233abe47 Mon Sep 17 00:00:00 2001 From: SKairinos Date: Sun, 22 Oct 2023 00:48:55 +0100 Subject: [PATCH] support indy students --- codeforlife/tests/api.py | 21 ++-- codeforlife/user/tests/views/test_user.py | 120 ++++++++++++++++------ 2 files changed, 103 insertions(+), 38 deletions(-) diff --git a/codeforlife/tests/api.py b/codeforlife/tests/api.py index ea0622a5..bf2dc70c 100644 --- a/codeforlife/tests/api.py +++ b/codeforlife/tests/api.py @@ -7,13 +7,13 @@ from django.db.models import Model from rest_framework.test import APITestCase as _APITestCase from rest_framework.test import APIClient as _APIClient -from rest_framework.serializers import BaseSerializer +from rest_framework.serializers import ModelSerializer from rest_framework.response import Response from ..user.models import User, AuthFactor -AnySerializer = t.TypeVar("AnySerializer", bound=BaseSerializer) +AnyModelSerializer = t.TypeVar("AnyModelSerializer", bound=ModelSerializer) AnyModel = t.TypeVar("AnyModel", bound=Model) @@ -78,17 +78,17 @@ def login(self, **credentials): def assert_data_equals_model( data: t.Dict[str, t.Any], model: AnyModel, - serializer_class: t.Type[AnySerializer], + model_serializer_class: t.Type[AnyModelSerializer], ): assert ( - data == serializer_class(model).data + data == model_serializer_class(model).data ), "Data does not equal serialized model." def retrieve( self, basename: str, model: AnyModel, - serializer_class: t.Type[AnySerializer], + model_serializer_class: t.Type[AnyModelSerializer], status_code_assertion: StatusCodeAssertion = None, **kwargs, ): @@ -102,7 +102,7 @@ def retrieve( self.assert_data_equals_model( response.json(), model, - serializer_class, + model_serializer_class, ) return response @@ -111,10 +111,15 @@ def list( self, basename: str, models: t.Iterable[AnyModel], - serializer_class: t.Type[AnySerializer], + model_serializer_class: t.Type[AnyModelSerializer], status_code_assertion: StatusCodeAssertion = None, **kwargs, ): + model_class: t.Type[AnyModel] = model_serializer_class.Meta.model + assert model_class.objects.difference( + model_class.objects.filter(pk__in=[model.pk for model in models]) + ).exists(), "List must exclude some models for a valid test." + response: Response = self.get( reverse(f"{basename}-list"), status_code_assertion=status_code_assertion, @@ -126,7 +131,7 @@ def list( self.assert_data_equals_model( data, model, - serializer_class, + model_serializer_class, ) return response diff --git a/codeforlife/user/tests/views/test_user.py b/codeforlife/user/tests/views/test_user.py index 95e8ea0a..940306ab 100644 --- a/codeforlife/user/tests/views/test_user.py +++ b/codeforlife/user/tests/views/test_user.py @@ -13,7 +13,7 @@ class TestUserViewSet(APITestCase): Base naming convention: test_{action} - action: This view set action. + action: The view set action. https://www.django-rest-framework.org/api-guide/viewsets/#viewset-actions """ @@ -78,7 +78,27 @@ def _login_student(self): assert user.student.class_field.teacher.school return user - def _get_other_user( + def _login_indy_student(self): + user = self.client.login( + email="indianajones@codeforlife.com", password="Password1" + ) + assert user.student + assert not user.student.class_field + return user + + def _get_other_school_user( + self, + user: User, + other_users: QuerySet[User], + is_teacher: bool, + ): + other_user = other_users.first() + assert other_user + assert user != other_user + assert other_user.teacher if is_teacher else other_user.student + return other_user + + def _get_another_school_user( self, user: User, other_users: QuerySet[User], @@ -90,24 +110,14 @@ def _get_other_user( if user.teacher else user.student.class_field.teacher.school ) - - other_user = other_users.first() - assert other_user - assert user != other_user - - if is_teacher: - assert other_user.teacher - other_school = other_user.teacher.school - else: - assert other_user.student - other_school = other_user.student.class_field.teacher.school - + other_user = self._get_other_school_user(user, other_users, is_teacher) + other_school = ( + other_user.teacher.school + if is_teacher + else other_user.student.class_field.teacher.school + ) assert other_school - if same_school: - assert school == other_school - else: - assert school != other_school - + assert school == other_school if same_school else school != other_school return other_user """ @@ -116,7 +126,8 @@ def _get_other_user( user_type: The type of user that is making the request. Options: - teacher: A teacher. - - student: A student. + - student: A school student. + - indy_student: A non-school student. other_user_type: The type of user whose data is being requested. Options: - self: User's own data. @@ -146,6 +157,7 @@ def test_retrieve__teacher__self(self): """ user = self._login_teacher() + self._retrieve_user(user) def test_retrieve__student__self(self): @@ -154,6 +166,16 @@ def test_retrieve__student__self(self): """ user = self._login_student() + + self._retrieve_user(user) + + def test_retrieve__indy_student__self(self): + """ + Independent student can retrieve their own user data. + """ + + user = self._login_indy_student() + self._retrieve_user(user) def test_retrieve__teacher__teacher__same_school(self): @@ -163,7 +185,7 @@ def test_retrieve__teacher__teacher__same_school(self): user = self._login_teacher() - other_user = self._get_other_user( + other_user = self._get_another_school_user( user, other_users=User.objects.exclude(id=user.id).filter( new_teacher__school=user.teacher.school @@ -181,7 +203,7 @@ def test_retrieve__teacher__student__same_school(self): user = self._login_teacher() - other_user = self._get_other_user( + other_user = self._get_another_school_user( user, other_users=User.objects.filter( new_student__class_field__teacher__school=user.teacher.school @@ -199,7 +221,7 @@ def test_retrieve__student__teacher__same_school(self): user = self._login_student() - other_user = self._get_other_user( + other_user = self._get_another_school_user( user, other_users=User.objects.filter( new_teacher__school=user.student.class_field.teacher.school @@ -220,7 +242,7 @@ def test_retrieve__student__student__same_school(self): user = self._login_student() - other_user = self._get_other_user( + other_user = self._get_another_school_user( user, other_users=User.objects.exclude(id=user.id).filter( new_student__class_field__teacher__school=user.student.class_field.teacher.school @@ -241,7 +263,7 @@ def test_retrieve__teacher__teacher__not_same_school(self): user = self._login_teacher() - other_user = self._get_other_user( + other_user = self._get_another_school_user( user, other_users=User.objects.exclude( new_teacher__school=user.teacher.school @@ -262,7 +284,7 @@ def test_retrieve__teacher__student__not_same_school(self): user = self._login_teacher() - other_user = self._get_other_user( + other_user = self._get_another_school_user( user, other_users=User.objects.exclude( new_student__class_field__teacher__school=user.teacher.school @@ -283,7 +305,7 @@ def test_retrieve__student__teacher__not_same_school(self): user = self._login_student() - other_user = self._get_other_user( + other_user = self._get_another_school_user( user, other_users=User.objects.exclude( new_teacher__school=user.student.class_field.teacher.school @@ -304,7 +326,7 @@ def test_retrieve__student__student__not_same_school(self): user = self._login_student() - other_user = self._get_other_user( + other_user = self._get_another_school_user( user, other_users=User.objects.exclude( new_student__class_field__teacher__school=user.student.class_field.teacher.school @@ -318,13 +340,42 @@ def test_retrieve__student__student__not_same_school(self): status_code_assertion=status.HTTP_404_NOT_FOUND, ) + def test_retrieve__indy_student__teacher(self): + """ + Independent student can not retrieve a teacher. + """ + + user = self._login_indy_student() + + self._get_other_school_user( + user, + other_users=User.objects.filter(new_teacher__school__isnull=False), + is_teacher=True, + ) + + def test_retrieve__indy_student__student(self): + """ + Independent student can not retrieve a student. + """ + + user = self._login_indy_student() + + self._get_other_school_user( + user, + other_users=User.objects.filter( + new_student__class_field__teacher__school__isnull=False + ), + is_teacher=False, + ) + """ List naming convention: test_list__{user_type} user_type: The type of user that is making the request. Options: - teacher: A teacher. - - student: A student. + - student: A school student. + - indy_student: A non-school student. """ def _list_users( @@ -355,9 +406,18 @@ def test_list__teacher(self): def test_list__student(self): """ - Student can list only themselves. + Student can list only themself. """ user = self._login_student() self._list_users([user]) + + def test_list__indy_student(self): + """ + Independent student can list only themself. + """ + + user = self._login_indy_student() + + self._list_users([user])