Добавлены интеграционные тесты создания тенантов

Создан файл tenants/tests/test_tenant_creation.py с 7 E2E тестами:

1. test_new_tenant_gets_all_5_payment_methods (КРИТИЧЕСКИЙ)
   - Проверяет что новый тенант получает все 5 способов оплаты
   - Включая account_balance (основной баг который исправили)
   - Проверяет правильность порядка, флагов, названий

2. test_new_tenant_gets_order_statuses
   - Проверяет создание системных статусов заказов
   - Минимум 3 статуса (draft, completed и другие)

3. test_new_tenant_gets_system_customer
   - Проверяет создание системного клиента
   - Для анонимных продаж

4. test_new_tenant_gets_superuser
   - Проверяет создание суперпользователя
   - С email из настроек TENANT_ADMIN_EMAIL

5. test_new_tenant_gets_domain
   - Проверяет создание домена
   - Формат: {schema_name}.localhost

6. test_registration_status_changes_to_approved
   - Проверяет изменение статуса заявки
   - PENDING → APPROVED

7. test_complete_tenant_onboarding (КОМПЛЕКСНЫЙ E2E)
   - Проверяет весь процесс онбординга
   - Все предыдущие проверки в одном тесте
   - Красивый вывод результата в консоль

Особенности:
- TransactionTestCase для работы с реальными схемами
- Создание администратора в setUp для каждого теста
- Автоматическая очистка схем в tearDown
- Вызов реального метода _approve_registration из админки
- Полное тестирование процесса как в продакшене

Результат: 2 главных теста прошли успешно ✓
test_new_tenant_gets_all_5_payment_methods: OK (10s)
test_complete_tenant_onboarding: OK (9.5s)
This commit is contained in:
2025-12-01 01:41:01 +03:00
parent 8a64b569bd
commit 490e5d5401
2 changed files with 369 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
"""
Тесты для приложения tenants
"""

View File

@@ -0,0 +1,365 @@
# -*- coding: utf-8 -*-
"""
Интеграционные тесты создания тенантов.
Проверяем полный процесс онбординга нового тенанта:
1. Создание схемы БД
2. Создание домена
3. Создание суперпользователя
4. Создание способов оплаты
5. Создание системных статусов заказов
6. Создание системного клиента
"""
from django.test import TestCase, TransactionTestCase
from django.db import connection
from django.contrib.auth import get_user_model
from django.conf import settings
from django_tenants.utils import schema_context
from tenants.models import Client, Domain, TenantRegistration
from orders.models import PaymentMethod, OrderStatus
from customers.models import Customer
User = get_user_model()
class TenantCreationIntegrationTest(TransactionTestCase):
"""
Интеграционный тест полного процесса создания тенанта.
TransactionTestCase используется потому что:
1. Нужно создавать реальные схемы БД
2. Нужно переключаться между схемами
3. Нужно очищать созданные схемы после теста
"""
def setUp(self):
"""Подготовка к каждому тесту"""
# Создаём администратора для каждого теста
self.admin_user = User.objects.create_superuser(
email='test_admin_per_test@example.com',
password='testpass123',
name='Test Admin'
)
def tearDown(self):
"""Очистка после каждого теста"""
# Удаляем все тестовые тенанты и их схемы
test_tenants = Client.objects.filter(schema_name__startswith='test_shop_')
for tenant in test_tenants:
schema_name = tenant.schema_name
# Удаляем схему вручную
with connection.cursor() as cursor:
cursor.execute(f'DROP SCHEMA IF EXISTS {schema_name} CASCADE')
# Удаляем запись тенанта
tenant.delete()
# Удаляем тестовые заявки
TenantRegistration.objects.filter(schema_name__startswith='test_shop_').delete()
def test_new_tenant_gets_all_5_payment_methods(self):
"""
КРИТИЧЕСКИЙ ТЕСТ: Новый тенант автоматически получает все 5 способов оплаты.
Это главный тест для проверки исправления бага с отсутствием account_balance.
"""
# 1. Создаём заявку на регистрацию
registration = TenantRegistration.objects.create(
shop_name='Тестовый магазин',
schema_name='test_shop_payment',
owner_email='owner@test.com',
owner_name='Тест Владелец',
phone='+375291111111',
status=TenantRegistration.STATUS_PENDING
)
# 2. Активируем заявку (как в админке)
from tenants.admin import TenantRegistrationAdmin
from django.contrib.admin.sites import AdminSite
admin = TenantRegistrationAdmin(TenantRegistration, AdminSite())
tenant = admin._approve_registration(registration, self.admin_user)
# 3. Проверяем что тенант создан
self.assertIsNotNone(tenant)
self.assertEqual(tenant.schema_name, 'test_shop_payment')
# 4. Переключаемся на схему нового тенанта
with schema_context('test_shop_payment'):
# 5. ГЛАВНАЯ ПРОВЕРКА: Все 5 способов оплаты созданы
payment_methods = PaymentMethod.objects.all().order_by('order')
self.assertEqual(
payment_methods.count(),
5,
f"Ожидалось 5 способов оплаты, получено {payment_methods.count()}"
)
# 6. Проверяем каждый способ оплаты по отдельности
expected_methods = [
('account_balance', 'С баланса счёта', 0),
('cash', 'Наличными', 1),
('card', 'Картой', 2),
('online', 'Онлайн', 3),
('legal_entity', 'Безнал от ЮРЛИЦ', 4),
]
for code, name, order in expected_methods:
method = PaymentMethod.objects.filter(code=code).first()
self.assertIsNotNone(
method,
f"Способ оплаты '{code}' не создан!"
)
self.assertEqual(method.name, name)
self.assertEqual(method.order, order)
self.assertTrue(method.is_system)
self.assertTrue(method.is_active)
# 7. Проверяем что account_balance на первом месте
first_method = payment_methods.first()
self.assertEqual(
first_method.code,
'account_balance',
f"Первый способ оплаты должен быть 'account_balance', но получен '{first_method.code}'"
)
def test_new_tenant_gets_order_statuses(self):
"""
Тест: Новый тенант получает системные статусы заказов.
"""
# Создаём и активируем тенант
registration = TenantRegistration.objects.create(
shop_name='Тестовый магазин статусы',
schema_name='test_shop_statuses',
owner_email='owner2@test.com',
owner_name='Тест Владелец 2',
phone='+375291111112',
status=TenantRegistration.STATUS_PENDING
)
from tenants.admin import TenantRegistrationAdmin
from django.contrib.admin.sites import AdminSite
admin = TenantRegistrationAdmin(TenantRegistration, AdminSite())
tenant = admin._approve_registration(registration, self.admin_user)
# Проверяем статусы заказов
with schema_context('test_shop_statuses'):
statuses = OrderStatus.objects.all()
# Должно быть минимум 3 основных статуса
self.assertGreaterEqual(
statuses.count(),
3,
"Должно быть создано минимум 3 системных статуса"
)
# Проверяем наличие ключевых статусов
draft_status = OrderStatus.objects.filter(code='draft').first()
self.assertIsNotNone(draft_status, "Статус 'draft' не создан")
self.assertTrue(draft_status.is_system)
completed_status = OrderStatus.objects.filter(code='completed').first()
self.assertIsNotNone(completed_status, "Статус 'completed' не создан")
self.assertTrue(completed_status.is_system)
def test_new_tenant_gets_system_customer(self):
"""
Тест: Новый тенант получает системного клиента для анонимных продаж.
"""
# Создаём и активируем тенант
registration = TenantRegistration.objects.create(
shop_name='Тестовый магазин клиенты',
schema_name='test_shop_customers',
owner_email='owner3@test.com',
owner_name='Тест Владелец 3',
phone='+375291111113',
status=TenantRegistration.STATUS_PENDING
)
from tenants.admin import TenantRegistrationAdmin
from django.contrib.admin.sites import AdminSite
admin = TenantRegistrationAdmin(TenantRegistration, AdminSite())
tenant = admin._approve_registration(registration, self.admin_user)
# Проверяем системного клиента
with schema_context('test_shop_customers'):
system_customer = Customer.objects.filter(is_system_customer=True).first()
self.assertIsNotNone(
system_customer,
"Системный клиент не создан"
)
self.assertTrue(system_customer.is_system_customer)
self.assertEqual(system_customer.name, 'Анонимный клиент')
def test_new_tenant_gets_superuser(self):
"""
Тест: Новый тенант получает суперпользователя для доступа к админке.
"""
# Создаём и активируем тенант
registration = TenantRegistration.objects.create(
shop_name='Тестовый магазин админ',
schema_name='test_shop_admin',
owner_email='owner4@test.com',
owner_name='Тест Владелец 4',
phone='+375291111114',
status=TenantRegistration.STATUS_PENDING
)
from tenants.admin import TenantRegistrationAdmin
from django.contrib.admin.sites import AdminSite
admin = TenantRegistrationAdmin(TenantRegistration, AdminSite())
tenant = admin._approve_registration(registration, self.admin_user)
# Проверяем суперпользователя
with schema_context('test_shop_admin'):
superuser = User.objects.filter(
email=settings.TENANT_ADMIN_EMAIL
).first()
self.assertIsNotNone(
superuser,
f"Суперпользователь с email {settings.TENANT_ADMIN_EMAIL} не создан"
)
self.assertTrue(superuser.is_superuser)
self.assertTrue(superuser.is_staff)
def test_new_tenant_gets_domain(self):
"""
Тест: Новый тенант получает домен для доступа.
"""
# Создаём и активируем тенант
registration = TenantRegistration.objects.create(
shop_name='Тестовый магазин домен',
schema_name='test_shop_domain',
owner_email='owner5@test.com',
owner_name='Тест Владелец 5',
phone='+375291111115',
status=TenantRegistration.STATUS_PENDING
)
from tenants.admin import TenantRegistrationAdmin
from django.contrib.admin.sites import AdminSite
admin = TenantRegistrationAdmin(TenantRegistration, AdminSite())
tenant = admin._approve_registration(registration, self.admin_user)
# Проверяем домен
domain = Domain.objects.filter(tenant=tenant).first()
self.assertIsNotNone(domain, "Домен не создан")
self.assertEqual(
domain.domain,
'test_shop_domain.localhost',
f"Ожидался домен 'test_shop_domain.localhost', получен '{domain.domain}'"
)
self.assertTrue(domain.is_primary)
def test_registration_status_changes_to_approved(self):
"""
Тест: После активации статус заявки меняется на APPROVED.
"""
# Создаём заявку
registration = TenantRegistration.objects.create(
shop_name='Тестовый магазин статус',
schema_name='test_shop_status',
owner_email='owner6@test.com',
owner_name='Тест Владелец 6',
phone='+375291111116',
status=TenantRegistration.STATUS_PENDING
)
# Проверяем начальный статус
self.assertEqual(registration.status, TenantRegistration.STATUS_PENDING)
# Активируем
from tenants.admin import TenantRegistrationAdmin
from django.contrib.admin.sites import AdminSite
admin = TenantRegistrationAdmin(TenantRegistration, AdminSite())
tenant = admin._approve_registration(registration, self.admin_user)
# Обновляем объект из БД
registration.refresh_from_db()
# Проверяем изменённый статус
self.assertEqual(registration.status, TenantRegistration.STATUS_APPROVED)
self.assertIsNotNone(registration.processed_at)
self.assertEqual(registration.processed_by, self.admin_user)
self.assertEqual(registration.tenant, tenant)
def test_complete_tenant_onboarding(self):
"""
КОМПЛЕКСНЫЙ ТЕСТ: Проверяем весь процесс онбординга тенанта.
Это E2E тест, который проверяет что при создании нового тенанта
создаются ВСЕ необходимые сущности.
"""
# Создаём и активируем тенант
registration = TenantRegistration.objects.create(
shop_name='Полный тестовый магазин',
schema_name='test_shop_complete',
owner_email='owner_complete@test.com',
owner_name='Тест Владелец Полный',
phone='+375291111117',
status=TenantRegistration.STATUS_PENDING
)
from tenants.admin import TenantRegistrationAdmin
from django.contrib.admin.sites import AdminSite
admin = TenantRegistrationAdmin(TenantRegistration, AdminSite())
tenant = admin._approve_registration(registration, self.admin_user)
# Проверяем тенант
self.assertIsNotNone(tenant)
self.assertTrue(tenant.is_active)
# Проверяем домен
domain = Domain.objects.filter(tenant=tenant).first()
self.assertIsNotNone(domain)
# Переключаемся на схему тенанта для проверки
with schema_context('test_shop_complete'):
# 1. Способы оплаты
payment_methods_count = PaymentMethod.objects.count()
self.assertEqual(payment_methods_count, 5, "Должно быть 5 способов оплаты")
# 2. Статусы заказов
order_statuses_count = OrderStatus.objects.count()
self.assertGreaterEqual(order_statuses_count, 3, "Должно быть минимум 3 статуса")
# 3. Системный клиент
system_customer = Customer.objects.filter(is_system_customer=True).first()
self.assertIsNotNone(system_customer, "Должен быть системный клиент")
# 4. Суперпользователь
superuser = User.objects.filter(email=settings.TENANT_ADMIN_EMAIL).first()
self.assertIsNotNone(superuser, "Должен быть суперпользователь")
# Проверяем заявку
registration.refresh_from_db()
self.assertEqual(registration.status, TenantRegistration.STATUS_APPROVED)
print("\n" + "=" * 70)
print("✓ ПОЛНЫЙ ОНБОРДИНГ ТЕНАНТА ПРОШЁЛ УСПЕШНО")
print("=" * 70)
print(f"Тенант: {tenant.name}")
print(f"Схема: {tenant.schema_name}")
print(f"Домен: {domain.domain}")
print(f"Способов оплаты: {payment_methods_count}")
print(f"Статусов заказов: {order_statuses_count}")
print(f"Системный клиент: ✓")
print(f"Суперпользователь: ✓")
print("=" * 70)