- Reformatted function signatures in `organization_service.py` and `task_service.py` for better alignment. - Updated import statements across multiple files for consistency and organization. - Enhanced test files by improving formatting and ensuring consistent use of async session factories. - Added type hints and improved type safety in various service and test files. - Adjusted `pyproject.toml` to include configuration for isort, mypy, and ruff for better code quality checks. - Cleaned up unused imports and organized existing ones in several test files.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
"""API tests for analytics endpoints."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
@@ -6,15 +7,14 @@ from datetime import datetime, timedelta, timezone
|
||||
from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
from httpx import AsyncClient
|
||||
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
|
||||
|
||||
from app.core.security import jwt_service
|
||||
from app.models.contact import Contact
|
||||
from app.models.deal import Deal, DealStage, DealStatus
|
||||
from app.models.organization import Organization
|
||||
from app.models.organization_member import OrganizationMember, OrganizationRole
|
||||
from app.models.user import User
|
||||
from httpx import AsyncClient
|
||||
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
@@ -26,10 +26,14 @@ class AnalyticsScenario:
|
||||
in_progress_deal_id: int
|
||||
|
||||
|
||||
async def prepare_analytics_scenario(session_factory: async_sessionmaker[AsyncSession]) -> AnalyticsScenario:
|
||||
async def prepare_analytics_scenario(
|
||||
session_factory: async_sessionmaker[AsyncSession],
|
||||
) -> AnalyticsScenario:
|
||||
async with session_factory() as session:
|
||||
org = Organization(name="Analytics Org")
|
||||
user = User(email="analytics@example.com", hashed_password="hashed", name="Analyst", is_active=True)
|
||||
user = User(
|
||||
email="analytics@example.com", hashed_password="hashed", name="Analyst", is_active=True
|
||||
)
|
||||
session.add_all([org, user])
|
||||
await session.flush()
|
||||
|
||||
@@ -103,7 +107,9 @@ async def prepare_analytics_scenario(session_factory: async_sessionmaker[AsyncSe
|
||||
user_id=user.id,
|
||||
user_email=user.email,
|
||||
token=token,
|
||||
in_progress_deal_id=next(deal.id for deal in deals if deal.status is DealStatus.IN_PROGRESS),
|
||||
in_progress_deal_id=next(
|
||||
deal.id for deal in deals if deal.status is DealStatus.IN_PROGRESS
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -113,7 +119,8 @@ def _headers(token: str, organization_id: int) -> dict[str, str]:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_deals_summary_endpoint_returns_metrics(
|
||||
session_factory: async_sessionmaker[AsyncSession], client: AsyncClient
|
||||
session_factory: async_sessionmaker[AsyncSession],
|
||||
client: AsyncClient,
|
||||
) -> None:
|
||||
scenario = await prepare_analytics_scenario(session_factory)
|
||||
|
||||
@@ -134,7 +141,8 @@ async def test_deals_summary_endpoint_returns_metrics(
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_deals_summary_respects_days_filter(
|
||||
session_factory: async_sessionmaker[AsyncSession], client: AsyncClient
|
||||
session_factory: async_sessionmaker[AsyncSession],
|
||||
client: AsyncClient,
|
||||
) -> None:
|
||||
scenario = await prepare_analytics_scenario(session_factory)
|
||||
|
||||
@@ -150,7 +158,8 @@ async def test_deals_summary_respects_days_filter(
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_deals_funnel_returns_breakdown(
|
||||
session_factory: async_sessionmaker[AsyncSession], client: AsyncClient
|
||||
session_factory: async_sessionmaker[AsyncSession],
|
||||
client: AsyncClient,
|
||||
) -> None:
|
||||
scenario = await prepare_analytics_scenario(session_factory)
|
||||
|
||||
@@ -162,7 +171,9 @@ async def test_deals_funnel_returns_breakdown(
|
||||
assert response.status_code == 200
|
||||
payload = response.json()
|
||||
assert len(payload["stages"]) == 4
|
||||
qualification = next(item for item in payload["stages"] if item["stage"] == DealStage.QUALIFICATION.value)
|
||||
qualification = next(
|
||||
item for item in payload["stages"] if item["stage"] == DealStage.QUALIFICATION.value
|
||||
)
|
||||
assert qualification["total"] == 1
|
||||
proposal = next(item for item in payload["stages"] if item["stage"] == DealStage.PROPOSAL.value)
|
||||
assert proposal["conversion_to_next"] == 100.0
|
||||
@@ -198,4 +209,4 @@ async def test_deal_update_invalidates_cached_summary(
|
||||
)
|
||||
assert refreshed.status_code == 200
|
||||
payload = refreshed.json()
|
||||
assert payload["won"]["count"] == 2
|
||||
assert payload["won"]["count"] == 2
|
||||
|
||||
Reference in New Issue
Block a user