Chore: Convert more testing to pytest style (#12678)

This commit is contained in:
Trenton H
2026-04-30 11:40:11 -07:00
committed by GitHub
parent 59c08e84e2
commit b38d112691
6 changed files with 845 additions and 626 deletions
+150 -115
View File
@@ -1,12 +1,13 @@
import types
from unittest.mock import patch
import pytest
import tantivy
from django.contrib.admin.sites import AdminSite
from django.contrib.auth.models import Permission
from django.contrib.auth.models import User
from django.test import Client
from django.test import TestCase
from django.utils import timezone
from pytest_mock import MockerFixture
from rest_framework import status
from documents.admin import DocumentAdmin
@@ -15,10 +16,28 @@ from documents.models import Document
from documents.models import Tag
from documents.search import get_backend
from documents.search import reset_backend
from documents.tests.factories import DocumentFactory
from documents.tests.factories import TagFactory
from documents.tests.factories import UserFactory
from documents.tests.utils import DirectoriesMixin
from paperless.admin import PaperlessUserAdmin
@pytest.fixture
def tag_admin() -> TagAdmin:
return TagAdmin(model=Tag, admin_site=AdminSite())
@pytest.fixture
def user_admin() -> PaperlessUserAdmin:
return PaperlessUserAdmin(model=User, admin_site=AdminSite())
@pytest.fixture
def staff_user(db) -> User:
return UserFactory.create(username="staff", staff=True)
class TestDocumentAdmin(DirectoriesMixin, TestCase):
def get_document_from_index(self, doc):
backend = get_backend()
@@ -41,160 +60,176 @@ class TestDocumentAdmin(DirectoriesMixin, TestCase):
super().tearDown()
def test_save_model(self) -> None:
doc = Document.objects.create(title="test")
doc = DocumentFactory.create(title="test")
doc.title = "new title"
self.doc_admin.save_model(None, doc, None, None)
self.assertEqual(Document.objects.get(id=doc.id).title, "new title")
self.assertEqual(self.get_document_from_index(doc)["id"], [doc.id])
def test_delete_model(self) -> None:
doc = Document.objects.create(title="test")
doc = DocumentFactory.create(title="test")
get_backend().add_or_update(doc)
self.assertIsNotNone(self.get_document_from_index(doc))
self.doc_admin.delete_model(None, doc)
self.assertRaises(Document.DoesNotExist, Document.objects.get, id=doc.id)
self.assertIsNone(self.get_document_from_index(doc))
def test_delete_queryset(self) -> None:
docs = []
for i in range(42):
doc = Document.objects.create(
title="Many documents with the same title",
checksum=f"{i:02}",
)
docs.append(doc)
get_backend().add_or_update(doc)
self.assertEqual(Document.objects.count(), 42)
docs = DocumentFactory.create_batch(
2,
title="Many documents with the same title",
)
for doc in docs:
get_backend().add_or_update(doc)
self.assertIsNotNone(self.get_document_from_index(doc))
self.doc_admin.delete_queryset(None, Document.objects.all())
self.assertEqual(Document.objects.count(), 0)
for doc in docs:
self.assertIsNone(self.get_document_from_index(doc))
def test_created(self) -> None:
doc = Document.objects.create(
title="test",
created=timezone.make_aware(timezone.datetime(2020, 4, 12)),
@pytest.mark.django_db
class TestTagAdmin:
def test_parent_tags_get_added(
self,
tag_admin: TagAdmin,
mocker: MockerFixture,
) -> None:
mock_bulk_update = mocker.patch(
"documents.tasks.bulk_update_documents.apply_async",
)
self.assertEqual(self.doc_admin.created_(doc), "2020-04-12")
class TestTagAdmin(DirectoriesMixin, TestCase):
def setUp(self) -> None:
super().setUp()
self.tag_admin = TagAdmin(model=Tag, admin_site=AdminSite())
@patch("documents.tasks.bulk_update_documents")
def test_parent_tags_get_added(self, mock_bulk_update) -> None:
document = Document.objects.create(title="test")
parent = Tag.objects.create(name="parent")
child = Tag.objects.create(name="child")
document = DocumentFactory.create(title="test")
parent = TagFactory.create(name="parent")
child = TagFactory.create(name="child")
document.tags.add(child)
child.tn_parent = parent
self.tag_admin.save_model(None, child, None, change=True)
tag_admin.save_model(None, child, None, change=True)
document.refresh_from_db()
self.assertIn(parent, document.tags.all())
class TestPaperlessAdmin(DirectoriesMixin, TestCase):
def setUp(self) -> None:
super().setUp()
self.user_admin = PaperlessUserAdmin(model=User, admin_site=AdminSite())
def test_request_is_passed_to_form(self) -> None:
user = User.objects.create(username="test", is_superuser=False)
non_superuser = User.objects.create(username="requestuser")
request = types.SimpleNamespace(user=non_superuser)
formType = self.user_admin.get_form(request)
form = formType(data={}, instance=user)
self.assertEqual(form.request, request)
def test_only_superuser_can_change_superuser(self) -> None:
superuser = User.objects.create_superuser(username="superuser", password="test")
non_superuser = User.objects.create(username="requestuser")
user = User.objects.create(username="test", is_superuser=False)
data = {
"username": "test",
"is_superuser": True,
assert parent in document.tags.all()
mock_bulk_update.assert_called_once()
assert mock_bulk_update.call_args.kwargs["kwargs"] == {
"document_ids": [document.id],
}
form = self.user_admin.form(data, instance=user)
@pytest.mark.django_db
class TestPaperlessAdmin:
def test_request_is_passed_to_form(
self,
user_admin: PaperlessUserAdmin,
) -> None:
user = UserFactory.create()
non_superuser = UserFactory.create()
request = types.SimpleNamespace(user=non_superuser)
form_type = user_admin.get_form(request)
form = form_type(data={}, instance=user)
assert form.request == request
def test_non_superuser_cannot_change_superuser_status(
self,
user_admin: PaperlessUserAdmin,
) -> None:
non_superuser = UserFactory.create()
user = UserFactory.create()
form = user_admin.form(
{"username": user.username, "is_superuser": True},
instance=user,
)
form.request = types.SimpleNamespace(user=non_superuser)
self.assertFalse(form.is_valid())
self.assertEqual(
form.errors.get("__all__"),
["Superuser status can only be changed by a superuser"],
assert not form.is_valid()
assert form.errors.get("__all__") == [
"Superuser status can only be changed by a superuser",
]
def test_superuser_can_change_superuser_status(
self,
user_admin: PaperlessUserAdmin,
admin_user: User,
) -> None:
user = UserFactory.create()
form = user_admin.form(
{"username": user.username, "is_superuser": True},
instance=user,
)
form.request = types.SimpleNamespace(user=admin_user)
form = self.user_admin.form(data, instance=user)
form.request = types.SimpleNamespace(user=superuser)
self.assertTrue(form.is_valid())
self.assertEqual({}, form.errors)
assert form.is_valid()
assert form.errors == {}
def test_superuser_can_only_be_modified_by_superuser(self) -> None:
superuser = User.objects.create_superuser(username="superuser", password="test")
user = User.objects.create(
username="test",
is_superuser=False,
is_staff=True,
@pytest.mark.parametrize(
("method", "perm_codename", "expected_message"),
[
pytest.param(
"patch",
"change_user",
"Superusers can only be modified by other superusers",
id="modify",
),
pytest.param(
"delete",
"delete_user",
"Superusers can only be deleted by other superusers",
id="delete",
),
],
)
def test_non_superuser_cannot_mutate_superuser(
self,
client: Client,
admin_user: User,
staff_user: User,
method: str,
perm_codename: str,
expected_message: str,
) -> None:
staff_user.user_permissions.add(
Permission.objects.get(codename=perm_codename),
)
change_user_perm = Permission.objects.get(codename="change_user")
user.user_permissions.add(change_user_perm)
client.force_login(staff_user)
self.client.force_login(user)
response = self.client.patch(
f"/api/users/{superuser.pk}/",
response = getattr(client, method)(
f"/api/users/{admin_user.pk}/",
{"first_name": "Updated"},
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(
response.content.decode(),
"Superusers can only be modified by other superusers",
)
self.client.logout()
self.client.force_login(superuser)
response = self.client.patch(
f"/api/users/{superuser.pk}/",
assert response.status_code == status.HTTP_403_FORBIDDEN
assert response.content.decode() == expected_message
assert User.objects.filter(pk=admin_user.pk).exists()
def test_superuser_can_modify_superuser(
self,
client: Client,
admin_user: User,
) -> None:
client.force_login(admin_user)
response = client.patch(
f"/api/users/{admin_user.pk}/",
{"first_name": "Updated"},
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
superuser.refresh_from_db()
self.assertEqual(superuser.first_name, "Updated")
def test_superuser_can_only_be_deleted_by_superuser(self):
superuser = User.objects.create_superuser(username="superuser", password="test")
user = User.objects.create(
username="test",
is_superuser=False,
is_staff=True,
)
delete_user_perm = Permission.objects.get(codename="delete_user")
user.user_permissions.add(delete_user_perm)
assert response.status_code == status.HTTP_200_OK
admin_user.refresh_from_db()
assert admin_user.first_name == "Updated"
self.client.force_login(user)
response = self.client.delete(f"/api/users/{superuser.pk}/")
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(
response.content.decode(),
"Superusers can only be deleted by other superusers",
)
self.assertTrue(User.objects.filter(pk=superuser.pk).exists())
def test_superuser_can_delete_superuser(
self,
client: Client,
admin_user: User,
) -> None:
target = UserFactory.create(superuser=True)
client.force_login(admin_user)
self.client.logout()
self.client.force_login(superuser)
response = self.client.delete(f"/api/users/{superuser.pk}/")
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertFalse(User.objects.filter(pk=superuser.pk).exists())
response = client.delete(f"/api/users/{target.pk}/")
assert response.status_code == status.HTTP_204_NO_CONTENT
assert not User.objects.filter(pk=target.pk).exists()