Law/tests/admin/base.py
2026-03-17 00:49:39 +03:00

150 lines
6.2 KiB
Python

import os
import json
import re
import unittest
from datetime import datetime, timedelta, timezone
from uuid import UUID, uuid4
from fastapi.testclient import TestClient
from sqlalchemy import create_engine, delete
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import StaticPool
# Ensure settings can be initialized in test environments
os.environ.setdefault("DATABASE_URL", "sqlite+pysqlite:///:memory:")
os.environ.setdefault("REDIS_URL", "redis://localhost:6379/0")
os.environ.setdefault("S3_ENDPOINT", "http://localhost:9000")
os.environ.setdefault("S3_ACCESS_KEY", "test")
os.environ.setdefault("S3_SECRET_KEY", "test")
os.environ.setdefault("S3_BUCKET", "test")
from app.core.config import settings
from app.core.security import create_jwt, verify_password
from app.db.session import get_db
from app.main import app
from app.models.admin_user import AdminUser
from app.models.admin_user_topic import AdminUserTopic
from app.models.attachment import Attachment
from app.models.audit_log import AuditLog
from app.models.client import Client
from app.models.form_field import FormField
from app.models.message import Message
from app.models.notification import Notification
from app.models.invoice import Invoice
from app.models.table_availability import TableAvailability
from app.models.quote import Quote
from app.models.request import Request
from app.models.status import Status
from app.models.status_group import StatusGroup
from app.models.status_history import StatusHistory
from app.models.topic_data_template import TopicDataTemplate
from app.models.topic import Topic
from app.models.topic_required_field import TopicRequiredField
from app.models.request_data_requirement import RequestDataRequirement
from app.models.request_service_request import RequestServiceRequest
from app.models.topic_status_transition import TopicStatusTransition
class AdminUniversalCrudBase(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.engine = create_engine(
"sqlite+pysqlite:///:memory:",
connect_args={"check_same_thread": False},
poolclass=StaticPool,
)
cls.SessionLocal = sessionmaker(bind=cls.engine, autocommit=False, autoflush=False)
AdminUser.__table__.create(bind=cls.engine)
Client.__table__.create(bind=cls.engine)
Quote.__table__.create(bind=cls.engine)
FormField.__table__.create(bind=cls.engine)
Request.__table__.create(bind=cls.engine)
StatusGroup.__table__.create(bind=cls.engine)
Status.__table__.create(bind=cls.engine)
Message.__table__.create(bind=cls.engine)
Attachment.__table__.create(bind=cls.engine)
StatusHistory.__table__.create(bind=cls.engine)
Topic.__table__.create(bind=cls.engine)
TopicRequiredField.__table__.create(bind=cls.engine)
TopicDataTemplate.__table__.create(bind=cls.engine)
RequestDataRequirement.__table__.create(bind=cls.engine)
RequestServiceRequest.__table__.create(bind=cls.engine)
TopicStatusTransition.__table__.create(bind=cls.engine)
AdminUserTopic.__table__.create(bind=cls.engine)
Notification.__table__.create(bind=cls.engine)
Invoice.__table__.create(bind=cls.engine)
TableAvailability.__table__.create(bind=cls.engine)
AuditLog.__table__.create(bind=cls.engine)
@classmethod
def tearDownClass(cls):
AuditLog.__table__.drop(bind=cls.engine)
Notification.__table__.drop(bind=cls.engine)
Invoice.__table__.drop(bind=cls.engine)
TableAvailability.__table__.drop(bind=cls.engine)
AdminUserTopic.__table__.drop(bind=cls.engine)
RequestDataRequirement.__table__.drop(bind=cls.engine)
RequestServiceRequest.__table__.drop(bind=cls.engine)
TopicDataTemplate.__table__.drop(bind=cls.engine)
TopicRequiredField.__table__.drop(bind=cls.engine)
TopicStatusTransition.__table__.drop(bind=cls.engine)
Topic.__table__.drop(bind=cls.engine)
StatusHistory.__table__.drop(bind=cls.engine)
Attachment.__table__.drop(bind=cls.engine)
Message.__table__.drop(bind=cls.engine)
Status.__table__.drop(bind=cls.engine)
StatusGroup.__table__.drop(bind=cls.engine)
Request.__table__.drop(bind=cls.engine)
FormField.__table__.drop(bind=cls.engine)
Quote.__table__.drop(bind=cls.engine)
Client.__table__.drop(bind=cls.engine)
AdminUser.__table__.drop(bind=cls.engine)
cls.engine.dispose()
def setUp(self):
with self.SessionLocal() as db:
db.execute(delete(AuditLog))
db.execute(delete(StatusHistory))
db.execute(delete(Attachment))
db.execute(delete(Message))
db.execute(delete(Request))
db.execute(delete(StatusGroup))
db.execute(delete(Client))
db.execute(delete(Status))
db.execute(delete(FormField))
db.execute(delete(Topic))
db.execute(delete(TopicRequiredField))
db.execute(delete(TopicDataTemplate))
db.execute(delete(RequestDataRequirement))
db.execute(delete(RequestServiceRequest))
db.execute(delete(TopicStatusTransition))
db.execute(delete(AdminUserTopic))
db.execute(delete(Notification))
db.execute(delete(Invoice))
db.execute(delete(TableAvailability))
db.execute(delete(Quote))
db.execute(delete(AdminUser))
db.commit()
def override_get_db():
db = self.SessionLocal()
try:
yield db
finally:
db.close()
app.dependency_overrides[get_db] = override_get_db
self.client = TestClient(app)
def tearDown(self):
self.client.close()
app.dependency_overrides.clear()
@staticmethod
def _auth_headers(role: str, email: str | None = None, sub: str | None = None) -> dict[str, str]:
token = create_jwt(
{"sub": str(sub or uuid4()), "email": email or f"{role.lower()}@example.com", "role": role},
settings.ADMIN_JWT_SECRET,
timedelta(minutes=30),
)
return {"Authorization": f"Bearer {token}"}