From 10d240892a052b1d954c7a069643b013ae1a0fbb Mon Sep 17 00:00:00 2001 From: mongkok <5514990+mongkok@users.noreply.github.com> Date: Fri, 4 Aug 2023 16:02:39 +0700 Subject: [PATCH] Added ResolveInfoTestCase --- tests/test_decorators.py | 36 ++++++++-------- tests/test_middleware.py | 89 +++++++++++++++++++++------------------- tests/testcases.py | 13 ++++-- 3 files changed, 74 insertions(+), 64 deletions(-) diff --git a/tests/test_decorators.py b/tests/test_decorators.py index c14d5cf..7b05fbb 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -4,16 +4,16 @@ from graphql_jwt import decorators, exceptions from .decorators import override_jwt_settings -from .testcases import TestCase +from .testcases import ResolveInfoTestCase -class UserPassesTests(TestCase): +class UserPassesTests(ResolveInfoTestCase): def test_user_passes_test(self): result = decorators.user_passes_test( lambda u: u.pk == self.user.pk, )( lambda info: None - )(self.info(self.user)) + )(self.info_mock(self.user)) self.assertIsNone(result) @@ -23,14 +23,14 @@ def test_permission_denied(self): )(lambda info: None) with self.assertRaises(exceptions.PermissionDenied): - func(self.info(self.user)) + func(self.info_mock(self.user)) -class LoginRequiredTests(TestCase): +class LoginRequiredTests(ResolveInfoTestCase): def test_login_required(self): result = decorators.login_required( lambda info: None, - )(self.info(self.user)) + )(self.info_mock(self.user)) self.assertIsNone(result) @@ -38,16 +38,16 @@ def test_permission_denied(self): func = decorators.login_required(lambda info: None) with self.assertRaises(exceptions.PermissionDenied): - func(self.info(AnonymousUser())) + func(self.info_mock(AnonymousUser())) -class StaffMemberRequiredTests(TestCase): +class StaffMemberRequiredTests(ResolveInfoTestCase): def test_staff_member_required(self): self.user.is_staff = True result = decorators.staff_member_required( lambda info: None, - )(self.info(self.user)) + )(self.info_mock(self.user)) self.assertIsNone(result) @@ -55,16 +55,16 @@ def test_permission_denied(self): func = decorators.staff_member_required(lambda info: None) with self.assertRaises(exceptions.PermissionDenied): - func(self.info(self.user)) + func(self.info_mock(self.user)) -class SuperuserRequiredTests(TestCase): +class SuperuserRequiredTests(ResolveInfoTestCase): def test_superuser_required(self): self.user.is_superuser = True result = decorators.superuser_required( lambda info: None, - )(self.info(self.user)) + )(self.info_mock(self.user)) self.assertIsNone(result) @@ -72,17 +72,17 @@ def test_permission_denied(self): func = decorators.superuser_required(lambda info: None) with self.assertRaises(exceptions.PermissionDenied): - func(self.info(self.user)) + func(self.info_mock(self.user)) -class PermissionRequiredTests(TestCase): +class PermissionRequiredTests(ResolveInfoTestCase): def test_permission_required(self): perm = Permission.objects.get(codename="add_user") self.user.user_permissions.add(perm) result = decorators.permission_required("auth.add_user")( lambda info: None, - )(self.info(self.user)) + )(self.info_mock(self.user)) self.assertIsNone(result) @@ -92,13 +92,13 @@ def test_permission_denied(self): )(lambda info: None) with self.assertRaises(exceptions.PermissionDenied): - func(self.info(self.user)) + func(self.info_mock(self.user)) -class CSRFRotationTests(TestCase): +class CSRFRotationTests(ResolveInfoTestCase): @override_jwt_settings(JWT_CSRF_ROTATION=True) def test_csrf_rotation(self): - info_mock = self.info(AnonymousUser()) + info_mock = self.info_mock(AnonymousUser()) decorators.csrf_rotation( lambda cls, root, info, *args, **kwargs: None, )(self, None, info_mock) diff --git a/tests/test_middleware.py b/tests/test_middleware.py index c20e96f..2cca8a8 100644 --- a/tests/test_middleware.py +++ b/tests/test_middleware.py @@ -2,15 +2,19 @@ from django.contrib.auth.models import AnonymousUser +import graphene +from graphql import OperationDefinitionNode, OperationType + +import graphql_jwt from graphql_jwt.exceptions import JSONWebTokenError from graphql_jwt.middleware import JSONWebTokenMiddleware, allow_any from graphql_jwt.settings import jwt_settings from .decorators import override_jwt_settings -from .testcases import TestCase +from .testcases import ResolveInfoTestCase -class AuthenticateByHeaderTests(TestCase): +class AuthenticateByHeaderTests(ResolveInfoTestCase): def setUp(self): super().setUp() self.middleware = JSONWebTokenMiddleware() @@ -24,7 +28,7 @@ def test_authenticate(self): } next_mock = mock.Mock() - info_mock = self.info(AnonymousUser(), **headers) + info_mock = self.info_mock(user=AnonymousUser(), headers=headers) self.middleware.resolve(next_mock, None, info_mock) @@ -41,7 +45,7 @@ def test_not_authenticate(self, authenticate_mock): } next_mock = mock.Mock() - info_mock = self.info(AnonymousUser(), **headers) + info_mock = self.info_mock(user=AnonymousUser(), headers=headers) self.middleware.resolve(next_mock, None, info_mock) @@ -58,7 +62,7 @@ def test_invalid_token(self): } next_mock = mock.Mock() - info_mock = self.info(AnonymousUser(), **headers) + info_mock = self.info_mock(user=AnonymousUser(), headers=headers) with self.assertRaises(JSONWebTokenError): self.middleware.resolve(next_mock, None, info_mock) @@ -74,7 +78,7 @@ def test_already_authenticated(self, authenticate_mock): } next_mock = mock.Mock() - info_mock = self.info(self.user, **headers) + info_mock = self.info_mock(user=self.user, headers=headers) self.middleware.resolve(next_mock, None, info_mock) @@ -90,7 +94,7 @@ def test_allow_any(self): } next_mock = mock.Mock() - info_mock = self.info(AnonymousUser(), **headers) + info_mock = self.info_mock(user=AnonymousUser(), headers=headers) self.middleware.resolve(next_mock, None, info_mock) @@ -98,22 +102,23 @@ def test_allow_any(self): self.assertIsInstance(info_mock.context.user, AnonymousUser) def test_authenticate_context(self): - info_mock = self.info() + info_mock = self.info_mock(path=["path"]) - self.middleware.cached_allow_any.add("test") + self.middleware.cached_allow_any.add("path") authenticate_context = self.middleware.authenticate_context(info_mock) self.assertFalse(authenticate_context) -class AuthenticateByArgumentTests(TestCase): +class AuthenticateByArgumentTests(ResolveInfoTestCase): @override_jwt_settings(JWT_ALLOW_ARGUMENT=True) def setUp(self): super().setUp() self.middleware = JSONWebTokenMiddleware() @override_jwt_settings( - JWT_ALLOW_ARGUMENT=True, JWT_ALLOW_ANY_HANDLER=lambda *args, **kwargs: False + JWT_ALLOW_ARGUMENT=True, + JWT_ALLOW_ANY_HANDLER=lambda *args, **kwargs: False, ) def test_authenticate(self): kwargs = { @@ -121,7 +126,7 @@ def test_authenticate(self): } next_mock = mock.Mock() - info_mock = self.info(AnonymousUser()) + info_mock = self.info_mock(AnonymousUser()) self.middleware.resolve(next_mock, None, info_mock, **kwargs) @@ -134,8 +139,7 @@ def test_authenticate(self): @override_jwt_settings(JWT_ALLOW_ARGUMENT=True) def test_authenticate_parent(self): next_mock = mock.Mock() - info_mock = self.info(AnonymousUser()) - info_mock.path = ["0", "1"] + info_mock = self.info_mock(user=AnonymousUser(), path=["0", "1"]) self.middleware.cached_authentication.insert(["0"], self.user) self.middleware.resolve(next_mock, None, info_mock) @@ -146,7 +150,7 @@ def test_authenticate_parent(self): @override_jwt_settings(JWT_ALLOW_ARGUMENT=True) def test_clear_authentication(self): next_mock = mock.Mock() - info_mock = self.info(self.user) + info_mock = self.info_mock(self.user) self.middleware.resolve(next_mock, None, info_mock) @@ -156,7 +160,7 @@ def test_clear_authentication(self): @override_jwt_settings(JWT_ALLOW_ARGUMENT=True) def test_clear_session_authentication(self): next_mock = mock.Mock() - info_mock = self.info(self.user) + info_mock = self.info_mock(self.user) info_mock.context.session = self.client.session self.middleware.resolve(next_mock, None, info_mock) @@ -167,7 +171,7 @@ def test_clear_session_authentication(self): @override_jwt_settings(JWT_ALLOW_ARGUMENT=True) def test_context_has_not_attr_user(self): next_mock = mock.Mock() - info_mock = self.info() + info_mock = self.info_mock() self.middleware.resolve(next_mock, None, info_mock) @@ -175,47 +179,48 @@ def test_context_has_not_attr_user(self): self.assertFalse(hasattr(info_mock.context, "user")) -class AllowAnyTests(TestCase): - def info(self, user, **headers): - info_mock = super().info(user, **headers) - info_mock.field_name = "test" - info_mock.operation.operation.value = "query" - return info_mock +class AllowAnyMutation(graphene.Mutation): + def mutate(root, info): + return None - def info_with_field_mock(self, user, field=None): - info_mock = self.info(user) - info_mock.schema.query_type = mock.Mock( - fields={ - "test": field, - } - ) - return info_mock - def info_with_type_mock(self, user, type=None): - type_mock = mock.Mock(type=mock.Mock(graphene_type=type)) - return self.info_with_field_mock(user, type_mock) +class AllowAnyTests(ResolveInfoTestCase): + def info_mock(self, user, **kwargs): + class Mutation(graphene.ObjectType): + test = AllowAnyMutation.Field() + verify = graphql_jwt.Verify.Field() + + schema = graphene.Schema(mutation=Mutation).graphql_schema + operation = OperationDefinitionNode(operation=OperationType("mutation")) + + return super().info_mock( + user=user, + schema=schema, + operation=operation, + **kwargs, + ) - @override_jwt_settings(JWT_ALLOW_ANY_CLASSES=["tests.testcases.TestCase"]) + @override_jwt_settings(JWT_ALLOW_ANY_CLASSES=[f"{__name__}.AllowAnyMutation"]) def test_allow_any(self): - info_mock = self.info_with_type_mock(self.user, TestCase) + info_mock = self.info_mock(self.user, field_name="test") allowed = allow_any(info_mock) self.assertTrue(allowed) - def test_not_allow_any(self): - info_mock = self.info_with_type_mock(self.user, TestCase) + def test_allow_jwt_mutations(self): + info_mock = self.info_mock(user=self.user, field_name="verify") allowed = allow_any(info_mock) - self.assertFalse(allowed) + self.assertTrue(allowed) def test_unknown_field(self): - info_mock = self.info_with_field_mock(self.user) + info_mock = self.info_mock(self.user) allowed = allow_any(info_mock) self.assertFalse(allowed) - def test_unknown_type(self): - info_mock = self.info_with_type_mock(self.user) + def test_not_allow_any(self): + info_mock = self.info_mock(self.user, field_name="test") allowed = allow_any(info_mock) self.assertFalse(allowed) diff --git a/tests/testcases.py b/tests/testcases.py index 4bdd641..11d2010 100644 --- a/tests/testcases.py +++ b/tests/testcases.py @@ -6,7 +6,6 @@ import graphene from graphene_django.views import GraphQLView -from graphql.execution.execute import GraphQLResolveInfo from graphql_jwt.decorators import jwt_cookie from graphql_jwt.settings import jwt_settings @@ -29,16 +28,22 @@ def setUp(self): self.token = jwt_encode(self.payload) self.request_factory = RequestFactory() - def info(self, user=None, **headers): - request = self.request_factory.post("/", **headers) + +class ResolveInfoTestCase(TestCase): + def info_mock(self, user=None, path=None, headers=None, **kwargs): + request = self.request_factory.post("/", **(headers or {})) if user is not None: request.user = user + if path is None: + path = [""] + return mock.Mock( context=request, - path=["test"], + path=path, spec=graphene.ResolveInfo, + **kwargs, )