From 58c62e54244d435bc8c6cb97e4266acc4f9afb22 Mon Sep 17 00:00:00 2001 From: Trenton H <797416+stumpylog@users.noreply.github.com> Date: Tue, 3 Mar 2026 13:45:01 -0800 Subject: [PATCH] Chore: convert test_adapter.py to pytest style --- src/paperless/tests/test_adapter.py | 192 ++++++++++++---------------- 1 file changed, 84 insertions(+), 108 deletions(-) diff --git a/src/paperless/tests/test_adapter.py b/src/paperless/tests/test_adapter.py index fcbd21b12..680abdd77 100644 --- a/src/paperless/tests/test_adapter.py +++ b/src/paperless/tests/test_adapter.py @@ -1,107 +1,100 @@ -from unittest import mock +import logging +import pytest from allauth.account.adapter import get_adapter from allauth.core import context from allauth.socialaccount.adapter import get_adapter as get_social_adapter -from django.conf import settings from django.contrib.auth.models import AnonymousUser from django.contrib.auth.models import Group from django.contrib.auth.models import User from django.forms import ValidationError from django.http import HttpRequest -from django.test import TestCase -from django.test import override_settings from django.urls import reverse +from pytest_django.fixtures import SettingsWrapper +from pytest_mock import MockerFixture from rest_framework.authtoken.models import Token from paperless.adapter import DrfTokenStrategy -class TestCustomAccountAdapter(TestCase): - def test_is_open_for_signup(self) -> None: +@pytest.mark.django_db +class TestCustomAccountAdapter: + def test_is_open_for_signup(self, settings: SettingsWrapper) -> None: adapter = get_adapter() # With no accounts, signups should be allowed - self.assertTrue(adapter.is_open_for_signup(None)) + assert adapter.is_open_for_signup(None) User.objects.create_user("testuser") - # Test when ACCOUNT_ALLOW_SIGNUPS is True settings.ACCOUNT_ALLOW_SIGNUPS = True - self.assertTrue(adapter.is_open_for_signup(None)) + assert adapter.is_open_for_signup(None) - # Test when ACCOUNT_ALLOW_SIGNUPS is False settings.ACCOUNT_ALLOW_SIGNUPS = False - self.assertFalse(adapter.is_open_for_signup(None)) + assert not adapter.is_open_for_signup(None) - def test_is_safe_url(self) -> None: + def test_is_safe_url(self, settings: SettingsWrapper) -> None: request = HttpRequest() - request.get_host = mock.Mock(return_value="example.com") + request.get_host = lambda: "example.com" with context.request_context(request): adapter = get_adapter() - with override_settings(ALLOWED_HOSTS=["*"]): - # True because request host is same - url = "https://example.com" - self.assertTrue(adapter.is_safe_url(url)) - url = "https://evil.com" + settings.ALLOWED_HOSTS = ["*"] + # True because request host is same + assert adapter.is_safe_url("https://example.com") # False despite wildcard because request host is different - self.assertFalse(adapter.is_safe_url(url)) + assert not adapter.is_safe_url("https://evil.com") settings.ALLOWED_HOSTS = ["example.com"] - url = "https://example.com" # True because request host is same - self.assertTrue(adapter.is_safe_url(url)) + assert adapter.is_safe_url("https://example.com") settings.ALLOWED_HOSTS = ["*", "example.com"] - url = "//evil.com" # False because request host is not in allowed hosts - self.assertFalse(adapter.is_safe_url(url)) + assert not adapter.is_safe_url("//evil.com") - @mock.patch("allauth.core.internal.ratelimit.consume", return_value=True) - def test_pre_authenticate(self, mock_consume) -> None: + def test_pre_authenticate( + self, + settings: SettingsWrapper, + mocker: MockerFixture, + ) -> None: + mocker.patch("allauth.core.internal.ratelimit.consume", return_value=True) adapter = get_adapter() request = HttpRequest() - request.get_host = mock.Mock(return_value="example.com") + request.get_host = lambda: "example.com" settings.DISABLE_REGULAR_LOGIN = False adapter.pre_authenticate(request) settings.DISABLE_REGULAR_LOGIN = True - with self.assertRaises(ValidationError): + with pytest.raises(ValidationError): adapter.pre_authenticate(request) - def test_get_reset_password_from_key_url(self) -> None: + def test_get_reset_password_from_key_url(self, settings: SettingsWrapper) -> None: request = HttpRequest() - request.get_host = mock.Mock(return_value="foo.org") + request.get_host = lambda: "foo.org" with context.request_context(request): adapter = get_adapter() - # Test when PAPERLESS_URL is None - with override_settings( - PAPERLESS_URL=None, - ACCOUNT_DEFAULT_HTTP_PROTOCOL="https", - ): - expected_url = f"https://foo.org{reverse('account_reset_password_from_key', kwargs={'uidb36': 'UID', 'key': 'KEY'})}" - self.assertEqual( - adapter.get_reset_password_from_key_url("UID-KEY"), - expected_url, - ) + settings.PAPERLESS_URL = None + settings.ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https" + expected_url = f"https://foo.org{reverse('account_reset_password_from_key', kwargs={'uidb36': 'UID', 'key': 'KEY'})}" + assert adapter.get_reset_password_from_key_url("UID-KEY") == expected_url - # Test when PAPERLESS_URL is not None - with override_settings(PAPERLESS_URL="https://bar.com"): - expected_url = f"https://bar.com{reverse('account_reset_password_from_key', kwargs={'uidb36': 'UID', 'key': 'KEY'})}" - self.assertEqual( - adapter.get_reset_password_from_key_url("UID-KEY"), - expected_url, - ) + settings.PAPERLESS_URL = "https://bar.com" + expected_url = f"https://bar.com{reverse('account_reset_password_from_key', kwargs={'uidb36': 'UID', 'key': 'KEY'})}" + assert adapter.get_reset_password_from_key_url("UID-KEY") == expected_url - @override_settings(ACCOUNT_DEFAULT_GROUPS=["group1", "group2"]) - def test_save_user_adds_groups(self) -> None: + def test_save_user_adds_groups( + self, + settings: SettingsWrapper, + mocker: MockerFixture, + ) -> None: + settings.ACCOUNT_DEFAULT_GROUPS = ["group1", "group2"] Group.objects.create(name="group1") user = User.objects.create_user("testuser") adapter = get_adapter() - form = mock.Mock( + form = mocker.MagicMock( cleaned_data={ "username": "testuser", "email": "user@example.com", @@ -110,88 +103,81 @@ class TestCustomAccountAdapter(TestCase): user = adapter.save_user(HttpRequest(), user, form, commit=True) - self.assertEqual(user.groups.count(), 1) - self.assertTrue(user.groups.filter(name="group1").exists()) - self.assertFalse(user.groups.filter(name="group2").exists()) + assert user.groups.count() == 1 + assert user.groups.filter(name="group1").exists() + assert not user.groups.filter(name="group2").exists() - def test_fresh_install_save_creates_superuser(self) -> None: + def test_fresh_install_save_creates_superuser(self, mocker: MockerFixture) -> None: adapter = get_adapter() - form = mock.Mock( + form = mocker.MagicMock( cleaned_data={ "username": "testuser", "email": "user@paperless-ngx.com", }, ) user = adapter.save_user(HttpRequest(), User(), form, commit=True) - self.assertTrue(user.is_superuser) + assert user.is_superuser - # Next time, it should not create a superuser - form = mock.Mock( + form = mocker.MagicMock( cleaned_data={ "username": "testuser2", "email": "user2@paperless-ngx.com", }, ) user2 = adapter.save_user(HttpRequest(), User(), form, commit=True) - self.assertFalse(user2.is_superuser) + assert not user2.is_superuser -class TestCustomSocialAccountAdapter(TestCase): - def test_is_open_for_signup(self) -> None: +class TestCustomSocialAccountAdapter: + @pytest.mark.django_db + def test_is_open_for_signup(self, settings: SettingsWrapper) -> None: adapter = get_social_adapter() - # Test when SOCIALACCOUNT_ALLOW_SIGNUPS is True settings.SOCIALACCOUNT_ALLOW_SIGNUPS = True - self.assertTrue(adapter.is_open_for_signup(None, None)) + assert adapter.is_open_for_signup(None, None) - # Test when SOCIALACCOUNT_ALLOW_SIGNUPS is False settings.SOCIALACCOUNT_ALLOW_SIGNUPS = False - self.assertFalse(adapter.is_open_for_signup(None, None)) + assert not adapter.is_open_for_signup(None, None) def test_get_connect_redirect_url(self) -> None: adapter = get_social_adapter() - request = None - socialaccount = None + assert adapter.get_connect_redirect_url(None, None) == reverse("base") - # Test the default URL - expected_url = reverse("base") - self.assertEqual( - adapter.get_connect_redirect_url(request, socialaccount), - expected_url, - ) - - @override_settings(SOCIAL_ACCOUNT_DEFAULT_GROUPS=["group1", "group2"]) - def test_save_user_adds_groups(self) -> None: + @pytest.mark.django_db + def test_save_user_adds_groups( + self, + settings: SettingsWrapper, + mocker: MockerFixture, + ) -> None: + settings.SOCIAL_ACCOUNT_DEFAULT_GROUPS = ["group1", "group2"] Group.objects.create(name="group1") adapter = get_social_adapter() - request = HttpRequest() user = User.objects.create_user("testuser") - sociallogin = mock.Mock( - user=user, - ) + sociallogin = mocker.MagicMock(user=user) - user = adapter.save_user(request, sociallogin, None) + user = adapter.save_user(HttpRequest(), sociallogin, None) - self.assertEqual(user.groups.count(), 1) - self.assertTrue(user.groups.filter(name="group1").exists()) - self.assertFalse(user.groups.filter(name="group2").exists()) + assert user.groups.count() == 1 + assert user.groups.filter(name="group1").exists() + assert not user.groups.filter(name="group2").exists() - def test_error_logged_on_authentication_error(self) -> None: + def test_error_logged_on_authentication_error( + self, + caplog: pytest.LogCaptureFixture, + ) -> None: adapter = get_social_adapter() - request = HttpRequest() - with self.assertLogs("paperless.auth", level="INFO") as log_cm: + with caplog.at_level(logging.INFO, logger="paperless.auth"): adapter.on_authentication_error( - request, + HttpRequest(), provider="test-provider", error="Error", exception="Test authentication error", ) - self.assertTrue( - any("Test authentication error" in message for message in log_cm.output), - ) + assert any("Test authentication error" in msg for msg in caplog.messages) -class TestDrfTokenStrategy(TestCase): +@pytest.mark.django_db +class TestDrfTokenStrategy: def test_create_access_token_creates_new_token(self) -> None: """ GIVEN: @@ -201,7 +187,6 @@ class TestDrfTokenStrategy(TestCase): THEN: - A new token is created and its key is returned """ - user = User.objects.create_user("testuser") request = HttpRequest() request.user = user @@ -209,13 +194,9 @@ class TestDrfTokenStrategy(TestCase): strategy = DrfTokenStrategy() token_key = strategy.create_access_token(request) - # Verify a token was created - self.assertIsNotNone(token_key) - self.assertTrue(Token.objects.filter(user=user).exists()) - - # Verify the returned key matches the created token - token = Token.objects.get(user=user) - self.assertEqual(token_key, token.key) + assert token_key is not None + assert Token.objects.filter(user=user).exists() + assert token_key == Token.objects.get(user=user).key def test_create_access_token_returns_existing_token(self) -> None: """ @@ -226,7 +207,6 @@ class TestDrfTokenStrategy(TestCase): THEN: - The same token key is returned (no new token created) """ - user = User.objects.create_user("testuser") existing_token = Token.objects.create(user=user) @@ -236,11 +216,8 @@ class TestDrfTokenStrategy(TestCase): strategy = DrfTokenStrategy() token_key = strategy.create_access_token(request) - # Verify the existing token key is returned - self.assertEqual(token_key, existing_token.key) - - # Verify only one token exists (no duplicate created) - self.assertEqual(Token.objects.filter(user=user).count(), 1) + assert token_key == existing_token.key + assert Token.objects.filter(user=user).count() == 1 def test_create_access_token_returns_none_for_unauthenticated_user(self) -> None: """ @@ -251,12 +228,11 @@ class TestDrfTokenStrategy(TestCase): THEN: - None is returned and no token is created """ - request = HttpRequest() request.user = AnonymousUser() strategy = DrfTokenStrategy() token_key = strategy.create_access_token(request) - self.assertIsNone(token_key) - self.assertEqual(Token.objects.count(), 0) + assert token_key is None + assert Token.objects.count() == 0