Files
octopus/myproject/customers/tests/test_system_customer.py
Andrey Smakotin dbbac933af Добавлены тесты защиты системного клиента и рефакторинг структуры тестов
- Создан новый класс 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)
2025-12-28 00:32:45 +03:00

136 lines
6.7 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.
# -*- 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(),
"Обычный клиент должен быть удалён"
)