Добавлены тесты защиты системного клиента и рефакторинг структуры тестов
- Создан новый класс SystemCustomerProtectionTestCase с 5 критичными тестами - Тест создания системного клиента с правильными атрибутами - Тест защиты от удаления системного клиента (ValidationError) - Тест защиты email системного клиента от изменения - Тест защиты флага is_system_customer от изменения - Тест что обычные клиенты не затронуты защитой - Исправлена логика в Customer.save(): проверка теперь использует original.is_system_customer - Добавлен импорт ValidationError из django.core.exceptions - Рефакторинг структуры тестов customers: - Разделены тесты по отдельным модулям в папке customers/tests/ - test_search_strategies.py - тесты стратегий поиска - test_system_customer.py - тесты защиты системного клиента - test_wallet_balance.py - тесты баланса кошелька - test_wallet_service.py - тесты WalletService - test_wallet_model.py - тесты модели WalletTransaction - Обновлён анализ тестов: 50 тестов (было 45), все проходят успешно - Критичная функциональность POS системы теперь покрыта тестами - Учтена tenant-система (используется TenantTestCase)
This commit is contained in:
135
myproject/customers/tests/test_system_customer.py
Normal file
135
myproject/customers/tests/test_system_customer.py
Normal file
@@ -0,0 +1,135 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Тесты защиты системного клиента от изменений и удаления.
|
||||
|
||||
Системный клиент используется для анонимных продаж в POS системе
|
||||
и должен быть защищён от случайного изменения или удаления.
|
||||
|
||||
Используем TenantTestCase для корректной работы с tenant-системой.
|
||||
"""
|
||||
from django.core.exceptions import ValidationError
|
||||
from django_tenants.test.cases import TenantTestCase
|
||||
|
||||
from customers.models import Customer
|
||||
|
||||
|
||||
class SystemCustomerProtectionTestCase(TenantTestCase):
|
||||
"""
|
||||
Тесты защиты системного клиента от изменений и удаления.
|
||||
|
||||
Системный клиент используется для анонимных продаж в POS системе
|
||||
и должен быть защищён от случайного изменения или удаления.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
"""Создаём системного клиента для тестов."""
|
||||
self.system_customer, created = Customer.get_or_create_system_customer()
|
||||
self.regular_customer = Customer.objects.create(
|
||||
name="Обычный клиент",
|
||||
email="regular@test.com"
|
||||
)
|
||||
|
||||
def test_get_or_create_system_customer_creates_with_correct_attributes(self):
|
||||
"""
|
||||
Метод get_or_create_system_customer() создаёт клиента с правильными атрибутами.
|
||||
|
||||
Проверяем:
|
||||
- Фиксированный email: system@pos.customer
|
||||
- Флаг is_system_customer = True
|
||||
- Правильное имя и заметки
|
||||
"""
|
||||
# Удаляем существующего системного клиента для чистоты теста
|
||||
Customer.objects.filter(is_system_customer=True).delete()
|
||||
|
||||
# Создаём через метод класса
|
||||
customer, created = Customer.get_or_create_system_customer()
|
||||
|
||||
# Проверяем, что клиент действительно создан
|
||||
self.assertTrue(created, "Системный клиент должен быть создан")
|
||||
|
||||
# Проверяем атрибуты
|
||||
self.assertEqual(customer.email, "system@pos.customer")
|
||||
self.assertTrue(customer.is_system_customer)
|
||||
self.assertEqual(customer.name, "АНОНИМНЫЙ ПОКУПАТЕЛЬ (POS)")
|
||||
self.assertIn("SYSTEM_CUSTOMER", customer.notes)
|
||||
|
||||
# Проверяем идемпотентность - повторный вызов возвращает того же клиента
|
||||
customer2, created2 = Customer.get_or_create_system_customer()
|
||||
self.assertFalse(created2, "Системный клиент не должен создаваться повторно")
|
||||
self.assertEqual(customer.pk, customer2.pk, "Должен вернуться тот же клиент")
|
||||
|
||||
def test_system_customer_cannot_be_deleted(self):
|
||||
"""
|
||||
Системный клиент защищён от удаления через метод delete().
|
||||
|
||||
При попытке удаления должен подниматься ValidationError.
|
||||
Это критично для работы POS системы.
|
||||
"""
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
self.system_customer.delete()
|
||||
|
||||
self.assertIn("Нельзя удалить системного клиента", str(context.exception))
|
||||
|
||||
# Проверяем, что клиент действительно не удалён
|
||||
self.assertTrue(
|
||||
Customer.objects.filter(pk=self.system_customer.pk).exists(),
|
||||
"Системный клиент не должен быть удалён"
|
||||
)
|
||||
|
||||
def test_system_customer_email_cannot_be_changed(self):
|
||||
"""
|
||||
Email системного клиента защищён от изменения.
|
||||
|
||||
Фиксированный email "system@pos.customer" используется для поиска
|
||||
системного клиента в POS системе. Изменение приведёт к сбоям.
|
||||
"""
|
||||
original_email = self.system_customer.email
|
||||
|
||||
# Пытаемся изменить email
|
||||
self.system_customer.email = "hacker@evil.com"
|
||||
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
self.system_customer.save()
|
||||
|
||||
self.assertIn("Нельзя изменить email системного клиента", str(context.exception))
|
||||
|
||||
# Проверяем, что email остался прежним в БД
|
||||
self.system_customer.refresh_from_db()
|
||||
self.assertEqual(self.system_customer.email, original_email)
|
||||
|
||||
def test_system_customer_flag_cannot_be_removed(self):
|
||||
"""
|
||||
Флаг is_system_customer защищён от изменения.
|
||||
|
||||
Нельзя "превратить" системного клиента в обычного,
|
||||
это нарушит логику POS системы.
|
||||
"""
|
||||
# Пытаемся снять флаг системного клиента
|
||||
self.system_customer.is_system_customer = False
|
||||
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
self.system_customer.save()
|
||||
|
||||
self.assertIn("Нельзя изменить флаг системного клиента", str(context.exception))
|
||||
|
||||
# Проверяем, что флаг остался True в БД
|
||||
self.system_customer.refresh_from_db()
|
||||
self.assertTrue(self.system_customer.is_system_customer)
|
||||
|
||||
def test_regular_customer_can_be_deleted_normally(self):
|
||||
"""
|
||||
Обычный клиент (не системный) может быть удалён без ограничений.
|
||||
|
||||
Защита применяется ТОЛЬКО к системному клиенту.
|
||||
Это гарантирует, что мы не сломали обычный функционал удаления.
|
||||
"""
|
||||
customer_pk = self.regular_customer.pk
|
||||
|
||||
# Удаление должно пройти успешно
|
||||
self.regular_customer.delete()
|
||||
|
||||
# Проверяем, что клиент действительно удалён
|
||||
self.assertFalse(
|
||||
Customer.objects.filter(pk=customer_pk).exists(),
|
||||
"Обычный клиент должен быть удалён"
|
||||
)
|
||||
Reference in New Issue
Block a user