Files
mostovik-backend/tests/apps/core/test_mixins.py
Aleksandr Meshchriakov 3d298ce352
Some checks failed
CI/CD Pipeline / Run Tests (pull_request) Successful in 1m53s
CI/CD Pipeline / Telegram Notify Success (push) Has been cancelled
CI/CD Pipeline / Run Tests (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (pull_request) Failing after 2m54s
CI/CD Pipeline / Telegram Notify Success (pull_request) Has been skipped
feat: expand platform APIs, sources, and test coverage
2026-03-17 12:56:48 +01:00

211 lines
7.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Тесты для Model Mixins."""
from apps.core.mixins import (
AuditMixin,
OrderableMixin,
SlugMixin,
SoftDeleteMixin,
StatusMixin,
TimestampMixin,
)
from django.db import connection, models
from django.test import TestCase, TransactionTestCase
from django.test.utils import isolate_apps
from tests.apps.user.factories import UserFactory
class TimestampMixinTest(TestCase):
"""Тесты для TimestampMixin."""
def test_created_at_auto_set(self):
"""Проверка автоматической установки created_at."""
# Используем BackgroundJob как пример модели с TimestampMixin
from apps.core.models import BackgroundJob
job = BackgroundJob.objects.create(
task_id="test-task-1",
task_name="test.task",
)
self.assertIsNotNone(job.created_at)
self.assertIsNotNone(job.updated_at)
def test_updated_at_auto_update(self):
"""Проверка автоматического обновления updated_at."""
from apps.core.models import BackgroundJob
job = BackgroundJob.objects.create(
task_id="test-task-2",
task_name="test.task",
)
original_updated = job.updated_at
# Обновляем запись
job.progress = 50
job.save()
job.refresh_from_db()
self.assertGreaterEqual(job.updated_at, original_updated)
class UUIDPrimaryKeyMixinTest(TestCase):
"""Тесты для UUIDPrimaryKeyMixin."""
def test_uuid_auto_generated(self):
"""Проверка автоматической генерации UUID."""
from apps.core.models import BackgroundJob
job = BackgroundJob.objects.create(
task_id="test-task-3",
task_name="test.task",
)
self.assertIsNotNone(job.id)
# Проверяем что ID похож на UUID (строка 32+ символа с дефисами)
self.assertEqual(len(str(job.id)), 36)
def test_uuid_unique(self):
"""Проверка уникальности UUID."""
from apps.core.models import BackgroundJob
job1 = BackgroundJob.objects.create(
task_id="test-task-4a",
task_name="test.task",
)
job2 = BackgroundJob.objects.create(
task_id="test-task-4b",
task_name="test.task",
)
self.assertNotEqual(job1.id, job2.id)
class SoftDeleteMixinTest(TestCase):
"""Тесты для SoftDeleteMixin."""
def test_soft_delete_mixin_fields(self):
"""Проверка наличия полей is_deleted и deleted_at."""
# Проверяем что поля определены в миксине
field_names = [f.name for f in SoftDeleteMixin._meta.get_fields()]
self.assertIn("is_deleted", field_names)
self.assertIn("deleted_at", field_names)
def test_soft_delete_queryset_methods(self):
"""Проверка методов SoftDeleteQuerySet."""
from apps.core.mixins import SoftDeleteQuerySet
# Проверяем что методы определены
self.assertTrue(hasattr(SoftDeleteQuerySet, "alive"))
self.assertTrue(hasattr(SoftDeleteQuerySet, "dead"))
self.assertTrue(hasattr(SoftDeleteQuerySet, "hard_delete"))
class StatusMixinTest(TestCase):
"""Тесты для StatusMixin."""
def test_status_choices(self):
"""Проверка наличия статусов."""
self.assertEqual(StatusMixin.Status.DRAFT, "draft")
self.assertEqual(StatusMixin.Status.ACTIVE, "active")
self.assertEqual(StatusMixin.Status.INACTIVE, "inactive")
self.assertEqual(StatusMixin.Status.ARCHIVED, "archived")
class OrderableMixinTest(TestCase):
"""Тесты для OrderableMixin."""
def test_orderable_mixin_has_order_field(self):
"""Проверка наличия поля order."""
self.assertTrue(hasattr(OrderableMixin, "order"))
@isolate_apps("apps.core")
class MixinsBehaviorTest(TransactionTestCase):
class TestModel(
SoftDeleteMixin,
OrderableMixin,
StatusMixin,
SlugMixin,
AuditMixin,
TimestampMixin,
models.Model,
):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Meta:
app_label = "core"
@classmethod
def setUpClass(cls):
super().setUpClass()
table_name = cls.TestModel._meta.db_table
existing_tables = connection.introspection.table_names()
with connection.schema_editor() as schema_editor:
if table_name in existing_tables:
schema_editor.delete_model(cls.TestModel)
schema_editor.create_model(cls.TestModel)
@classmethod
def tearDownClass(cls):
table_name = cls.TestModel._meta.db_table
with connection.schema_editor() as schema_editor:
if table_name in connection.introspection.table_names():
schema_editor.delete_model(cls.TestModel)
super().tearDownClass()
def test_soft_delete_and_restore(self):
user = UserFactory.create_user()
obj = self.TestModel.objects.create(
name=f"item-{user.id}",
slug=f"slug-{user.id}",
created_by=user,
)
obj.delete()
self.assertTrue(obj.is_deleted)
self.assertIsNotNone(obj.deleted_at)
self.assertEqual(self.TestModel.objects.count(), 0)
self.assertEqual(self.TestModel.all_objects.count(), 1)
obj.restore()
self.assertFalse(obj.is_deleted)
self.assertEqual(self.TestModel.objects.count(), 1)
def test_soft_delete_queryset_methods(self):
obj = self.TestModel.objects.create(name="alive", slug="alive-slug")
self.TestModel.objects.filter(id=obj.id).delete()
self.assertEqual(self.TestModel.objects.count(), 0)
self.assertEqual(self.TestModel.objects.deleted_only().count(), 1)
def test_hard_delete(self):
obj = self.TestModel.objects.create(name="hard", slug="hard-slug")
obj.hard_delete()
self.assertEqual(self.TestModel.all_objects.count(), 0)
def test_orderable_moves(self):
obj = self.TestModel.objects.create(name="ord", slug="ord-slug", order=2)
obj.move_up()
obj.refresh_from_db()
self.assertEqual(obj.order, 1)
obj.move_down()
obj.refresh_from_db()
self.assertEqual(obj.order, 2)
obj.move_to(5)
obj.refresh_from_db()
self.assertEqual(obj.order, 5)
obj.move_to(-1)
obj.refresh_from_db()
self.assertEqual(obj.order, 5)
def test_status_transitions(self):
obj = self.TestModel.objects.create(name="status", slug="status-slug")
self.assertTrue(obj.is_draft)
obj.activate()
obj.refresh_from_db()
self.assertTrue(obj.is_active_status)
obj.deactivate()
obj.refresh_from_db()
self.assertEqual(obj.status, obj.Status.INACTIVE)
obj.archive()
obj.refresh_from_db()
self.assertTrue(obj.is_archived)