1
0
mirror of https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git synced 2025-08-14 00:25:46 +02:00

Fix tests

This commit is contained in:
MoonTestUse1
2025-01-06 23:40:39 +06:00
parent 161361609d
commit fec52c777b
17 changed files with 249 additions and 368 deletions

View File

@@ -1,16 +1,13 @@
"""Settings configuration"""
import os
from pydantic_settings import BaseSettings, SettingsConfigDict
"""Application configuration"""
from functools import lru_cache
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
"""Application settings"""
PROJECT_NAME: str = "Support Service"
VERSION: str = "1.0.0"
API_V1_STR: str = "/api"
PROJECT_NAME: str = "Employee Request System"
# Database
TESTING: bool = os.getenv("TESTING", "False") == "True"
DATABASE_URL: str = "sqlite:///./test.db" if TESTING else "postgresql://postgres:postgres123@postgres:5432/support_db"
DATABASE_URL: str = "postgresql://postgres:postgres@localhost:5432/employee_requests"
# JWT
SECRET_KEY: str = "your-secret-key"
@@ -18,21 +15,16 @@ class Settings(BaseSettings):
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
# Redis
REDIS_HOST: str = "redis"
REDIS_HOST: str = "localhost"
REDIS_PORT: int = 6379
# Admin
ADMIN_USERNAME: str = "admin"
ADMIN_PASSWORD: str = "admin123"
class Config:
"""Pydantic config"""
case_sensitive = True
# Telegram
TELEGRAM_BOT_TOKEN: str = "your-bot-token"
TELEGRAM_CHAT_ID: str = "your-chat-id"
@lru_cache()
def get_settings() -> Settings:
"""Get cached settings"""
return Settings()
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=True
)
settings = Settings()
settings = get_settings()

View File

@@ -1,36 +1,24 @@
"""Test settings configuration"""
from pydantic_settings import BaseSettings, SettingsConfigDict
"""Test configuration"""
from pydantic_settings import BaseSettings
class TestSettings(BaseSettings):
"""Test application settings"""
PROJECT_NAME: str = "Support Service Test"
VERSION: str = "1.0.0"
API_V1_STR: str = "/api"
"""Test settings"""
PROJECT_NAME: str = "Employee Request System Test"
# Database
DATABASE_URL: str = "sqlite:///:memory:"
# JWT
SECRET_KEY: str = "test-secret-key"
SECRET_KEY: str = "test_secret_key"
ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
# Redis
REDIS_HOST: str = "redis"
REDIS_HOST: str = "localhost"
REDIS_PORT: int = 6379
# Admin
ADMIN_USERNAME: str = "admin"
ADMIN_PASSWORD: str = "admin123"
# Telegram
TELEGRAM_BOT_TOKEN: str = "test-bot-token"
TELEGRAM_CHAT_ID: str = "test-chat-id"
model_config = SettingsConfigDict(
env_file=".env.test",
env_file_encoding="utf-8",
case_sensitive=True
)
class Config:
"""Pydantic config"""
case_sensitive = True
test_settings = TestSettings()

View File

@@ -8,13 +8,7 @@ from . import employees
def create_request(db: Session, request: RequestCreate, employee_id: int) -> Request:
"""Create new request"""
# Получаем данные сотрудника
employee = employees.get_employee(db, employee_id)
if not employee:
raise ValueError("Employee not found")
db_request = Request(
department=employee.department, # Берем отдел из данных сотрудника
request_type=request.request_type,
description=request.description,
priority=request.priority,
@@ -30,27 +24,6 @@ def get_request(db: Session, request_id: int) -> Optional[Request]:
"""Get request by ID"""
return db.query(Request).filter(Request.id == request_id).first()
def get_request_details(db: Session, request_id: int) -> Optional[Dict]:
"""Get detailed request information including employee data"""
request = get_request(db, request_id)
if not request:
return None
employee = employees.get_employee(db, request.employee_id)
if not employee:
return None
return {
"id": request.id,
"request_type": request.request_type,
"description": request.description,
"priority": request.priority,
"status": request.status,
"department": request.department,
"created_at": request.created_at.isoformat(),
"employee_full_name": employee.full_name
}
def get_employee_requests(db: Session, employee_id: int) -> list[Request]:
"""Get employee's requests"""
return db.query(Request).filter(Request.employee_id == employee_id).all()
@@ -80,12 +53,6 @@ def get_statistics(db: Session) -> Dict:
func.count(Request.id)
).group_by(Request.status).all()
)
# Добавляем статусы с нулевым количеством
for status in RequestStatus:
if status not in by_status:
by_status[status] = 0
return {
"total": total,
"by_status": by_status

View File

@@ -1,39 +1,27 @@
"""Database configuration"""
"""Database module"""
import os
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from .core.config import settings
# Для создания таблиц импортируем модели
from .models.employee import Employee # noqa
from .models.request import Request # noqa
from .models.token import Token # noqa
# Определяем, используем ли тестовую базу данных
TESTING = os.getenv("TESTING", "False") == "True"
DATABASE_URL = "sqlite:///:memory:" if TESTING else settings.DATABASE_URL
def get_database_url():
"""Получение URL базы данных в зависимости от окружения."""
try:
from .core.test_config import test_settings
return test_settings.DATABASE_URL
except ImportError:
return settings.DATABASE_URL
# Создаем базовый класс для моделей
Base = declarative_base()
# Используем правильный URL для базы данных
SQLALCHEMY_DATABASE_URL = get_database_url()
# Создаем движок с нужными параметрами
connect_args = {}
if SQLALCHEMY_DATABASE_URL.startswith("sqlite"):
connect_args["check_same_thread"] = False
engine = create_engine(
SQLALCHEMY_DATABASE_URL,
connect_args=connect_args
)
# Создаем движок базы данных
connect_args = {"check_same_thread": False} if TESTING else {}
engine = create_engine(DATABASE_URL, connect_args=connect_args)
# Создаем фабрику сессий
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
def get_db():
"""Получение сессии базы данных."""
"""Get database session"""
db = SessionLocal()
try:
yield db

View File

@@ -1,7 +1,10 @@
"""Models initialization"""
from .base import Base
from ..database import Base, engine
from .employee import Employee
from .request import Request
from .token import Token
# Создаем все таблицы
Base.metadata.create_all(bind=engine)
__all__ = ['Base', 'Employee', 'Request', 'Token']

View File

@@ -1,10 +1,12 @@
"""Employee model"""
from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.sql import func
from sqlalchemy import Column, Integer, String, Boolean, DateTime
from sqlalchemy.orm import relationship
from .base import Base
from datetime import datetime
from ..database import Base
class Employee(Base):
"""Employee model"""
__tablename__ = "employees"
id = Column(Integer, primary_key=True, index=True)
@@ -13,7 +15,8 @@ class Employee(Base):
department = Column(String, nullable=False)
office = Column(String, nullable=False)
hashed_password = Column(String, nullable=False)
created_at = Column(DateTime(timezone=True), server_default=func.now())
is_active = Column(Boolean, default=True)
is_admin = Column(Boolean, default=False)
created_at = Column(DateTime, nullable=False, default=datetime.utcnow)
# Определяем отношение к Request
requests = relationship("Request", back_populates="employee", cascade="all, delete-orphan")
requests = relationship("Request", back_populates="employee")

View File

@@ -1,31 +1,41 @@
"""Request model"""
from enum import Enum
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime
from sqlalchemy.sql import func
from sqlalchemy import Column, Integer, String, Enum as SQLEnum, ForeignKey, DateTime
from sqlalchemy.orm import relationship
from .base import Base
from datetime import datetime
from ..database import Base
class RequestStatus(str, Enum):
"""Request status enum"""
NEW = "new"
IN_PROGRESS = "in_progress"
COMPLETED = "completed"
REJECTED = "rejected"
class RequestPriority(str, Enum):
"""Request priority enum"""
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
class RequestType(str, Enum):
"""Request type enum"""
VACATION = "vacation"
SICK_LEAVE = "sick_leave"
EQUIPMENT = "equipment"
OTHER = "other"
class Request(Base):
"""Request model"""
__tablename__ = "requests"
id = Column(Integer, primary_key=True, index=True)
request_type = Column(String, index=True)
description = Column(String)
priority = Column(String)
status = Column(String, default=RequestStatus.NEW)
employee_id = Column(Integer, ForeignKey("employees.id"))
created_at = Column(DateTime(timezone=True), server_default=func.now())
request_type = Column(SQLEnum(RequestType), nullable=False)
description = Column(String, nullable=False)
priority = Column(SQLEnum(RequestPriority), nullable=False, default=RequestPriority.MEDIUM)
status = Column(SQLEnum(RequestStatus), nullable=False, default=RequestStatus.NEW)
created_at = Column(DateTime, nullable=False, default=datetime.utcnow)
employee_id = Column(Integer, ForeignKey("employees.id"), nullable=False)
# Определяем отношение к Employee
employee = relationship("Employee", back_populates="requests")

View File

@@ -1,12 +1,14 @@
"""Token model"""
from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.sql import func
from .base import Base
from datetime import datetime
from ..database import Base
class Token(Base):
"""Token model"""
__tablename__ = "tokens"
id = Column(Integer, primary_key=True, index=True)
token = Column(String, unique=True, index=True)
user_id = Column(Integer, index=True) # -1 для админа, остальные для сотрудников
created_at = Column(DateTime(timezone=True), server_default=func.now())
employee_id = Column(Integer)
created_at = Column(DateTime, default=datetime.utcnow)

View File

@@ -42,16 +42,17 @@ async def admin_login(
db: Session = Depends(get_db)
):
"""Авторизация администратора"""
if form_data.username != "admin" or form_data.password != "admin123":
# Проверяем учетные данные администратора
employee = employees.get_employee_by_last_name(db, form_data.username)
if not employee or not employee.is_admin or not verify_password(form_data.password, employee.hashed_password):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
# Для админа используем специальный ID
admin_id = -1
access_token = create_and_save_token(admin_id, db)
# Создаем и сохраняем токен
access_token = create_and_save_token(employee.id, db)
return {
"access_token": access_token,

View File

@@ -8,6 +8,7 @@ class EmployeeBase(BaseModel):
last_name: str
department: str
office: str
is_admin: bool = False
model_config = ConfigDict(from_attributes=True)
@@ -19,6 +20,7 @@ class EmployeeUpdate(BaseModel):
last_name: Optional[str] = None
department: Optional[str] = None
office: Optional[str] = None
is_admin: Optional[bool] = None
model_config = ConfigDict(from_attributes=True)

View File

@@ -1,29 +1,30 @@
"""Request schemas"""
from pydantic import BaseModel, ConfigDict
from typing import Optional
from pydantic import BaseModel
from datetime import datetime
from ..models.request import RequestStatus, RequestPriority
from typing import Optional
from ..models.request import RequestStatus, RequestPriority, RequestType
class RequestBase(BaseModel):
request_type: str
"""Base request schema"""
request_type: RequestType
description: str
priority: RequestPriority
model_config = ConfigDict(from_attributes=True)
priority: RequestPriority = RequestPriority.MEDIUM
class RequestCreate(RequestBase):
"""Request create schema"""
pass
class RequestUpdate(BaseModel):
status: RequestStatus
model_config = ConfigDict(from_attributes=True)
class Request(RequestBase):
"""Request schema"""
id: int
status: RequestStatus
employee_id: int
department: Optional[str] = None
created_at: datetime
employee_id: int
model_config = ConfigDict(from_attributes=True)
class Config:
"""Pydantic config"""
from_attributes = True
class RequestUpdate(BaseModel):
"""Request update schema"""
status: RequestStatus

View File

@@ -7,7 +7,7 @@ import re
from .jwt import verify_token
from ..database import get_db
from ..models.employee import Employee
from ..crud import employees
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
security = HTTPBearer(auto_error=False)
@@ -23,7 +23,7 @@ def verify_password(plain_password: str, hashed_password: str) -> bool:
def get_current_admin(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: Session = Depends(get_db)
) -> Employee:
) -> dict:
"""Get current admin from token"""
if not credentials:
raise HTTPException(
@@ -37,28 +37,27 @@ def get_current_admin(
payload = verify_token(token, db)
employee_id = int(payload.get("sub"))
# Получаем сотрудника из БД
from ..crud.employees import get_employee
employee = get_employee(db, employee_id)
# Проверяем, что это админ
employee = employees.get_employee(db, employee_id)
if not employee or not employee.is_admin:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
status_code=status.HTTP_403_FORBIDDEN,
detail="Not enough permissions",
headers={"WWW-Authenticate": "Bearer"},
)
return employee
except Exception:
except Exception as e:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
detail="Invalid authentication credentials",
headers={"WWW-Authenticate": "Bearer"},
)
def get_current_employee(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: Session = Depends(get_db)
) -> Employee:
) -> dict:
"""Get current employee from token"""
if not credentials:
raise HTTPException(
@@ -72,13 +71,12 @@ def get_current_employee(
payload = verify_token(token, db)
employee_id = int(payload.get("sub"))
# Получаем сотрудника из БД
from ..crud.employees import get_employee
employee = get_employee(db, employee_id)
# Проверяем существование сотрудника
employee = employees.get_employee(db, employee_id)
if not employee:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
detail="Employee not found",
headers={"WWW-Authenticate": "Bearer"},
)
@@ -86,6 +84,6 @@ def get_current_employee(
except Exception:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
detail="Invalid authentication credentials",
headers={"WWW-Authenticate": "Bearer"},
)

View File

@@ -1,22 +1,13 @@
"""JWT utilities"""
from datetime import datetime, timedelta
from typing import Optional
from jose import JWTError, jwt
from fastapi import HTTPException, status
from redis import Redis
from sqlalchemy.orm import Session
from ..core.config import settings
from ..models.token import Token
from ..crud.employees import get_employee
redis = Redis(
host=settings.REDIS_HOST,
port=settings.REDIS_PORT,
decode_responses=True
)
def create_access_token(data: dict) -> str:
"""Create access token"""
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
@@ -24,59 +15,26 @@ def create_access_token(data: dict) -> str:
return encoded_jwt
def verify_token(token: str, db: Session) -> dict:
"""Verify token"""
try:
# Проверяем, что токен действителен
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
user_id: int = payload.get("sub")
if user_id is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
)
# Проверяем токен в Redis
if not redis.get(f"token:{token}"):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
)
return payload
except JWTError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
)
return None
def create_and_save_token(user_id: int, db: Session) -> str:
# Создаем JWT токен
access_token = create_access_token({"sub": str(user_id)})
def create_and_save_token(employee_id: int, db: Session) -> str:
"""Create and save token"""
# Создаем токен
access_token = create_access_token({"sub": str(employee_id)})
# Сохраняем в БД
# Сохраняем токен в базу
db_token = Token(
token=access_token,
user_id=user_id
employee_id=employee_id
)
db.add(db_token)
db.commit()
db.refresh(db_token)
# Кэшируем в Redis
redis.setex(
f"token:{access_token}",
timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES),
"valid"
)
return access_token
def get_current_employee(token: str, db: Session):
payload = verify_token(token, db)
employee_id = int(payload.get("sub"))
if employee_id == -1: # Для админа
return {"is_admin": True}
employee = get_employee(db, employee_id)
if employee is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Employee not found",
)
return employee
return access_token

View File

@@ -1,129 +1,110 @@
"""Test configuration."""
"""Test fixtures"""
import os
import pytest
from typing import Generator
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import StaticPool
from unittest.mock import patch
import fakeredis.aioredis
from typing import Generator
from app.core.test_config import test_settings
from app.database import get_db
from app.models.base import Base
# Устанавливаем флаг тестирования
os.environ["TESTING"] = "True"
from app.main import app
from app.database import Base, get_db
from app.models.employee import Employee
from app.utils.auth import get_password_hash
# Создаем тестовую базу данных в памяти
SQLALCHEMY_DATABASE_URL = "sqlite:///:memory:"
engine = create_engine(
test_settings.DATABASE_URL,
SQLALCHEMY_DATABASE_URL,
connect_args={"check_same_thread": False},
poolclass=StaticPool
poolclass=StaticPool,
)
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
class MockRedis:
"""Мок для Redis."""
def __init__(self):
self.data = {}
# Создаем тестовую базу данных
Base.metadata.create_all(bind=engine)
def get(self, key):
return self.data.get(key)
def set(self, key, value, ex=None):
self.data[key] = value
return True
def delete(self, key):
if key in self.data:
del self.data[key]
return True
def exists(self, key):
return key in self.data
@pytest.fixture(scope="function")
def redis_mock():
"""Фикстура для мока Redis."""
with patch("app.utils.jwt.redis") as mock:
redis_instance = MockRedis()
mock.get.side_effect = redis_instance.get
mock.set.side_effect = redis_instance.set
mock.delete.side_effect = redis_instance.delete
mock.exists.side_effect = redis_instance.exists
yield mock
@pytest.fixture(scope="function")
@pytest.fixture
def db() -> Generator:
"""Фикстура для создания тестовой базы данных."""
Base.metadata.create_all(bind=engine)
db = TestingSessionLocal()
try:
yield db
finally:
db.close()
Base.metadata.drop_all(bind=engine)
"""Фикстура для получения тестовой сессии БД."""
connection = engine.connect()
transaction = connection.begin()
session = TestingSessionLocal(bind=connection)
yield session
session.close()
transaction.rollback()
connection.close()
@pytest.fixture(scope="function")
def client(db: TestingSessionLocal, redis_mock) -> Generator:
"""Фикстура для создания тестового клиента."""
@pytest.fixture
def client(db) -> TestClient:
"""Фикстура для получения тестового клиента."""
def override_get_db():
try:
yield db
finally:
db.close()
pass
# Импортируем app здесь, чтобы использовать тестовые настройки
from app.main import get_application
app = get_application(test_settings)
app.dependency_overrides[get_db] = override_get_db
return TestClient(app)
yield TestClient(app)
app.dependency_overrides.clear()
@pytest.fixture(scope="function")
def test_employee(db: TestingSessionLocal) -> Employee:
@pytest.fixture
def test_employee(db) -> Employee:
"""Фикстура для создания тестового сотрудника."""
employee = Employee(
first_name="Test",
last_name="User",
department="IT",
office="101",
hashed_password=get_password_hash("testpassword")
last_name="Employee",
department="Test Department",
office="Test Office",
hashed_password=get_password_hash("testpassword"),
is_admin=False
)
db.add(employee)
db.commit()
db.refresh(employee)
return employee
@pytest.fixture(scope="function")
def test_admin(db: TestingSessionLocal) -> Employee:
@pytest.fixture
def test_admin(db) -> Employee:
"""Фикстура для создания тестового администратора."""
admin = Employee(
first_name="Admin",
last_name="User",
department="Administration",
office="100",
hashed_password=get_password_hash("adminpassword")
department="Admin Department",
office="Admin Office",
hashed_password=get_password_hash("adminpassword"),
is_admin=True
)
db.add(admin)
db.commit()
db.refresh(admin)
return admin
@pytest.fixture(scope="function")
def employee_token(test_employee: Employee, db: TestingSessionLocal) -> str:
"""Фикстура для создания токена тестового сотрудника."""
from app.utils.jwt import create_access_token
token = create_access_token({"sub": str(test_employee.id)})
# Сохраняем токен в Redis мок
from app.utils.jwt import redis
redis.set(f"token:{token}", "valid")
return token
@pytest.fixture
def employee_token(client: TestClient, test_employee: Employee) -> str:
"""Фикстура для получения токена сотрудника."""
response = client.post(
"/api/auth/login",
data={"username": test_employee.last_name, "password": "testpassword"}
)
return response.json()["access_token"]
@pytest.fixture(scope="function")
def admin_token(test_admin: Employee, db: TestingSessionLocal) -> str:
"""Фикстура для создания токена администратора."""
from app.utils.jwt import create_access_token
token = create_access_token({"sub": str(test_admin.id)})
# Сохраняем токен в Redis мок
from app.utils.jwt import redis
redis.set(f"token:{token}", "valid")
return token
@pytest.fixture
def admin_token(client: TestClient, test_admin: Employee) -> str:
"""Фикстура для получения токена администратора."""
response = client.post(
"/api/auth/admin/login",
data={"username": test_admin.last_name, "password": "adminpassword"}
)
return response.json()["access_token"]
@pytest.fixture
def redis_mock():
"""Фикстура для мока Redis."""
return fakeredis.aioredis.FakeRedis()

View File

@@ -8,7 +8,7 @@ def test_login_employee_success(client: TestClient, test_employee: Employee):
"""Тест успешной авторизации сотрудника."""
response = client.post(
"/api/auth/login",
data={"username": test_employee.email, "password": "testpassword"}
data={"username": test_employee.last_name, "password": "testpassword"}
)
assert response.status_code == 200
assert "access_token" in response.json()
@@ -19,7 +19,7 @@ def test_login_employee_wrong_password(client: TestClient, test_employee: Employ
"""Тест авторизации сотрудника с неверным паролем."""
response = client.post(
"/api/auth/login",
data={"username": test_employee.email, "password": "wrongpassword"}
data={"username": test_employee.last_name, "password": "wrongpassword"}
)
assert response.status_code == 401
assert response.json()["detail"] == "Incorrect username or password"
@@ -28,7 +28,7 @@ def test_login_employee_wrong_username(client: TestClient):
"""Тест авторизации с несуществующим пользователем."""
response = client.post(
"/api/auth/login",
data={"username": "nonexistent@example.com", "password": "testpassword"}
data={"username": "nonexistent", "password": "testpassword"}
)
assert response.status_code == 401
assert response.json()["detail"] == "Incorrect username or password"
@@ -37,7 +37,7 @@ def test_login_admin_success(client: TestClient, test_admin: Employee):
"""Тест успешной авторизации администратора."""
response = client.post(
"/api/auth/admin/login",
data={"username": test_admin.email, "password": "adminpassword"}
data={"username": test_admin.last_name, "password": "adminpassword"}
)
assert response.status_code == 200
assert "access_token" in response.json()
@@ -48,7 +48,7 @@ def test_login_admin_wrong_password(client: TestClient, test_admin: Employee):
"""Тест авторизации администратора с неверным паролем."""
response = client.post(
"/api/auth/admin/login",
data={"username": test_admin.email, "password": "wrongpassword"}
data={"username": test_admin.last_name, "password": "wrongpassword"}
)
assert response.status_code == 401
assert response.json()["detail"] == "Incorrect username or password"
@@ -61,8 +61,8 @@ def test_protected_route_with_valid_token(client: TestClient, employee_token: st
)
assert response.status_code == 200
data = response.json()
assert data["email"] == test_employee.email
assert data["full_name"] == test_employee.full_name
assert data["first_name"] == test_employee.first_name
assert data["last_name"] == test_employee.last_name
def test_protected_route_without_token(client: TestClient):
"""Тест доступа к защищенному маршруту без токена."""
@@ -77,4 +77,4 @@ def test_protected_route_with_invalid_token(client: TestClient):
headers={"Authorization": "Bearer invalid_token"}
)
assert response.status_code == 401
assert response.json()["detail"] == "Could not validate credentials"
assert response.json()["detail"] == "Invalid authentication credentials"

View File

@@ -10,19 +10,19 @@ def test_create_employee(client: TestClient, admin_token: str, db: Session):
"/api/employees",
headers={"Authorization": f"Bearer {admin_token}"},
json={
"email": "new@example.com",
"password": "newpassword",
"full_name": "New Employee",
"first_name": "New",
"last_name": "Employee",
"department": "IT",
"is_active": True,
"is_admin": False
"office": "102",
"password": "newpassword"
}
)
assert response.status_code == 201
data = response.json()
assert data["email"] == "new@example.com"
assert data["full_name"] == "New Employee"
assert data["first_name"] == "New"
assert data["last_name"] == "Employee"
assert data["department"] == "IT"
assert data["office"] == "102"
assert "id" in data
def test_create_employee_unauthorized(client: TestClient):
@@ -30,11 +30,11 @@ def test_create_employee_unauthorized(client: TestClient):
response = client.post(
"/api/employees",
json={
"email": "new@example.com",
"password": "newpassword",
"full_name": "New Employee",
"is_active": True,
"is_admin": False
"first_name": "New",
"last_name": "Employee",
"department": "IT",
"office": "102",
"password": "newpassword"
}
)
assert response.status_code == 401
@@ -50,9 +50,10 @@ def test_get_employees(client: TestClient, admin_token: str, test_employee: Empl
data = response.json()
assert isinstance(data, list)
assert len(data) > 0
assert "email" in data[0]
assert "full_name" in data[0]
assert "first_name" in data[0]
assert "last_name" in data[0]
assert "department" in data[0]
assert "office" in data[0]
def test_get_employee_by_id(client: TestClient, admin_token: str, test_employee: Employee, db: Session):
"""Тест получения сотрудника по ID."""
@@ -62,9 +63,10 @@ def test_get_employee_by_id(client: TestClient, admin_token: str, test_employee:
)
assert response.status_code == 200
data = response.json()
assert data["email"] == test_employee.email
assert data["full_name"] == test_employee.full_name
assert data["first_name"] == test_employee.first_name
assert data["last_name"] == test_employee.last_name
assert data["department"] == test_employee.department
assert data["office"] == test_employee.office
def test_get_nonexistent_employee(client: TestClient, admin_token: str):
"""Тест получения несуществующего сотрудника."""
@@ -81,18 +83,18 @@ def test_update_employee(client: TestClient, admin_token: str, test_employee: Em
f"/api/employees/{test_employee.id}",
headers={"Authorization": f"Bearer {admin_token}"},
json={
"email": "updated@example.com",
"full_name": "Updated Employee",
"first_name": "Updated",
"last_name": "Name",
"department": "HR",
"is_active": True,
"is_admin": False
"office": "103"
}
)
assert response.status_code == 200
data = response.json()
assert data["email"] == "updated@example.com"
assert data["full_name"] == "Updated Employee"
assert data["first_name"] == "Updated"
assert data["last_name"] == "Name"
assert data["department"] == "HR"
assert data["office"] == "103"
def test_delete_employee(client: TestClient, admin_token: str, test_employee: Employee, db: Session):
"""Тест удаления сотрудника."""
@@ -102,9 +104,10 @@ def test_delete_employee(client: TestClient, admin_token: str, test_employee: Em
)
assert response.status_code == 200
data = response.json()
assert data["email"] == test_employee.email
assert data["full_name"] == test_employee.full_name
assert data["first_name"] == test_employee.first_name
assert data["last_name"] == test_employee.last_name
assert data["department"] == test_employee.department
assert data["office"] == test_employee.office
def test_employee_me(client: TestClient, employee_token: str, test_employee: Employee, db: Session):
"""Тест получения информации о текущем сотруднике."""
@@ -114,9 +117,10 @@ def test_employee_me(client: TestClient, employee_token: str, test_employee: Emp
)
assert response.status_code == 200
data = response.json()
assert data["email"] == test_employee.email
assert data["full_name"] == test_employee.full_name
assert data["first_name"] == test_employee.first_name
assert data["last_name"] == test_employee.last_name
assert data["department"] == test_employee.department
assert data["office"] == test_employee.office
def test_update_me(client: TestClient, employee_token: str, test_employee: Employee, db: Session):
"""Тест обновления информации о текущем сотруднике."""
@@ -124,12 +128,15 @@ def test_update_me(client: TestClient, employee_token: str, test_employee: Emplo
"/api/employees/me",
headers={"Authorization": f"Bearer {employee_token}"},
json={
"full_name": "Updated Name",
"department": "Support"
"first_name": "Updated",
"last_name": "Name",
"department": "Support",
"office": "104"
}
)
assert response.status_code == 200
data = response.json()
assert data["full_name"] == "Updated Name"
assert data["email"] == test_employee.email
assert data["department"] == "Support"
assert data["first_name"] == "Updated"
assert data["last_name"] == "Name"
assert data["department"] == "Support"
assert data["office"] == "104"

View File

@@ -11,14 +11,14 @@ def test_create_request(client: TestClient, employee_token: str, db: Session):
"/api/requests",
headers={"Authorization": f"Bearer {employee_token}"},
json={
"request_type": "support",
"request_type": "equipment",
"description": "Test Description",
"priority": "medium"
}
)
assert response.status_code == 201
data = response.json()
assert data["request_type"] == "support"
assert data["request_type"] == "equipment"
assert data["description"] == "Test Description"
assert data["priority"] == "medium"
assert data["status"] == "new"
@@ -29,7 +29,7 @@ def test_create_request_unauthorized(client: TestClient):
response = client.post(
"/api/requests",
json={
"request_type": "support",
"request_type": "equipment",
"description": "Test Description",
"priority": "medium"
}
@@ -39,13 +39,9 @@ def test_create_request_unauthorized(client: TestClient):
def test_get_employee_requests(client: TestClient, employee_token: str, test_employee: Employee, db: Session):
"""Тест получения списка заявок сотрудника."""
db.add(test_employee)
db.commit()
db.refresh(test_employee)
# Создаем тестовую заявку
request = Request(
request_type="support",
request_type="equipment",
description="Test Description",
priority="medium",
status="new",
@@ -62,18 +58,14 @@ def test_get_employee_requests(client: TestClient, employee_token: str, test_emp
data = response.json()
assert isinstance(data, list)
assert len(data) > 0
assert data[0]["request_type"] == "support"
assert data[0]["request_type"] == "equipment"
assert data[0]["description"] == "Test Description"
def test_admin_get_all_requests(client: TestClient, admin_token: str, test_employee: Employee, db: Session):
"""Тест получения всех заявок администратором."""
db.add(test_employee)
db.commit()
db.refresh(test_employee)
# Создаем тестовую заявку
request = Request(
request_type="support",
request_type="equipment",
description="Test Description",
priority="medium",
status="new",
@@ -90,23 +82,18 @@ def test_admin_get_all_requests(client: TestClient, admin_token: str, test_emplo
data = response.json()
assert isinstance(data, list)
assert len(data) > 0
assert data[0]["request_type"] == "support"
assert data[0]["request_type"] == "equipment"
assert data[0]["description"] == "Test Description"
def test_update_request_status(client: TestClient, admin_token: str, test_employee: Employee, db: Session):
"""Тест обновления статуса заявки."""
db.add(test_employee)
db.commit()
db.refresh(test_employee)
# Создаем тестовую заявку
request = Request(
request_type="support",
request_type="equipment",
description="Test Description",
priority="medium",
status="new",
employee_id=test_employee.id,
department=test_employee.department
employee_id=test_employee.id
)
db.add(request)
db.commit()
@@ -122,35 +109,28 @@ def test_update_request_status(client: TestClient, admin_token: str, test_employ
def test_get_request_statistics(client: TestClient, admin_token: str, test_employee: Employee, db: Session):
"""Тест получения статистики по заявкам."""
db.add(test_employee)
db.commit()
db.refresh(test_employee)
# Создаем тестовые заявки с разными статусами
requests = [
Request(
request_type="support",
request_type="equipment",
description="Test Description",
priority="medium",
status="new",
employee_id=test_employee.id,
department=test_employee.department
employee_id=test_employee.id
),
Request(
request_type="support",
request_type="equipment",
description="Test Description",
priority="high",
status="in_progress",
employee_id=test_employee.id,
department=test_employee.department
employee_id=test_employee.id
),
Request(
request_type="support",
request_type="equipment",
description="Test Description",
priority="low",
status="completed",
employee_id=test_employee.id,
department=test_employee.department
employee_id=test_employee.id
)
]
for req in requests: